zx 2 سال پیش
کامیت
bae465e43a
100فایلهای تغییر یافته به همراه55338 افزوده شده و 0 حذف شده
  1. 65 0
      README.md
  2. 158 0
      keepalive+nginx服务部署ubuntu20.04.txt
  3. 148 0
      message.proto
  4. 113 0
      plc调度节点/CMakeLists.txt
  5. 60 0
      plc调度节点/README.md
  6. 729 0
      plc调度节点/communication/communication.pb.cc
  7. 530 0
      plc调度节点/communication/communication.pb.h
  8. 14 0
      plc调度节点/communication/communication.proto
  9. 93 0
      plc调度节点/communication/communication_message.cpp
  10. 148 0
      plc调度节点/communication/communication_message.h
  11. 608 0
      plc调度节点/communication/communication_socket_base.cpp
  12. 169 0
      plc调度节点/communication/communication_socket_base.h
  13. 994 0
      plc调度节点/dispatch/database_communication_configuration.pb.cc
  14. 752 0
      plc调度节点/dispatch/database_communication_configuration.pb.h
  15. 18 0
      plc调度节点/dispatch/database_communication_configuration.proto
  16. 572 0
      plc调度节点/dispatch/database_controller.cpp
  17. 148 0
      plc调度节点/dispatch/database_controller.h
  18. 875 0
      plc调度节点/dispatch/dispatch_command.cpp
  19. 175 0
      plc调度节点/dispatch/dispatch_command.h
  20. 558 0
      plc调度节点/dispatch/dispatch_communication.cpp
  21. 666 0
      plc调度节点/dispatch/dispatch_communication.h
  22. 629 0
      plc调度节点/dispatch/dispatch_coordinates.cpp
  23. 199 0
      plc调度节点/dispatch/dispatch_coordinates.h
  24. 218 0
      plc调度节点/dispatch/dispatch_ground_lidar.cpp
  25. 77 0
      plc调度节点/dispatch/dispatch_ground_lidar.h
  26. 1170 0
      plc调度节点/dispatch/dispatch_manager.cpp
  27. 252 0
      plc调度节点/dispatch/dispatch_manager.h
  28. 7243 0
      plc调度节点/dispatch/dispatch_parameter.pb.cc
  29. 4834 0
      plc调度节点/dispatch/dispatch_parameter.pb.h
  30. 214 0
      plc调度节点/dispatch/dispatch_parameter.proto
  31. 1156 0
      plc调度节点/dispatch/dispatch_plc.cpp
  32. 254 0
      plc调度节点/dispatch/dispatch_plc.h
  33. 289 0
      plc调度节点/dispatch/dispatch_singlechip.cpp
  34. 85 0
      plc调度节点/dispatch/dispatch_singlechip.h
  35. 387 0
      plc调度节点/error_code/error_code.cpp
  36. 777 0
      plc调度节点/error_code/error_code.h
  37. 14 0
      plc调度节点/hulitest.sh
  38. 220 0
      plc调度节点/main.cpp
  39. 4787 0
      plc调度节点/message/message.pb.cc
  40. 2984 0
      plc调度节点/message/message.pb.h
  41. 149 0
      plc调度节点/message/message.proto
  42. 4207 0
      plc调度节点/message/message_base.pb.cc
  43. 3120 0
      plc调度节点/message/message_base.pb.h
  44. 311 0
      plc调度节点/message/message_base.proto
  45. 28 0
      plc调度节点/proto.sh
  46. 1956 0
      plc调度节点/rabbitmq/rabbitmq.pb.cc
  47. 1620 0
      plc调度节点/rabbitmq/rabbitmq.pb.h
  48. 67 0
      plc调度节点/rabbitmq/rabbitmq.proto
  49. 1074 0
      plc调度节点/rabbitmq/rabbitmq_base.cpp
  50. 190 0
      plc调度节点/rabbitmq/rabbitmq_base.h
  51. 109 0
      plc调度节点/rabbitmq/rabbitmq_message.cpp
  52. 62 0
      plc调度节点/rabbitmq/rabbitmq_message.h
  53. 303 0
      plc调度节点/rabbitmq/ttt.cpp
  54. 105 0
      plc调度节点/rabbitmq/ttt.h
  55. 79 0
      plc调度节点/rabbitmq/胡力的rabbitmq-c说明文档.md
  56. 14 0
      plc调度节点/run_dispatch.sh
  57. 55 0
      plc调度节点/setting/communication.prototxt
  58. 54 0
      plc调度节点/setting/communication_a.prototxt
  59. 54 0
      plc调度节点/setting/communication_b.prototxt
  60. 54 0
      plc调度节点/setting/communication_c.prototxt
  61. 20 0
      plc调度节点/setting/database_communication.prototxt
  62. 3384 0
      plc调度节点/setting/dispatch_coordinates.prototxt
  63. 33 0
      plc调度节点/setting/dispatch_device.prototxt
  64. 86 0
      plc调度节点/setting/laser.prototxt
  65. 54 0
      plc调度节点/setting/locate.prototxt
  66. 183 0
      plc调度节点/setting/rabbitmq.prototxt
  67. 183 0
      plc调度节点/setting/rabbitmq_a.prototxt
  68. 185 0
      plc调度节点/setting/rabbitmq_b.prototxt
  69. 185 0
      plc调度节点/setting/rabbitmq_c.prototxt
  70. 16 0
      plc调度节点/setting/snap7_communication.prototxt
  71. 21 0
      plc调度节点/setting/snap7_communication_a.prototxt
  72. 16 0
      plc调度节点/setting/snap7_communication_b.prototxt
  73. 16 0
      plc调度节点/setting/snap7_communication_c.prototxt
  74. 182 0
      plc调度节点/snap7_communication/plc_data.cpp
  75. 75 0
      plc调度节点/snap7_communication/plc_data.h
  76. 85 0
      plc调度节点/snap7_communication/s7_plc.cpp
  77. 32 0
      plc调度节点/snap7_communication/s7_plc.h
  78. 236 0
      plc调度节点/snap7_communication/snap7_buf.cpp
  79. 85 0
      plc调度节点/snap7_communication/snap7_buf.h
  80. 686 0
      plc调度节点/snap7_communication/snap7_communication.pb.cc
  81. 439 0
      plc调度节点/snap7_communication/snap7_communication.pb.h
  82. 12 0
      plc调度节点/snap7_communication/snap7_communication.proto
  83. 384 0
      plc调度节点/snap7_communication/snap7_communication_base.cpp
  84. 112 0
      plc调度节点/snap7_communication/snap7_communication_base.h
  85. 112 0
      plc调度节点/system/system_communication.cpp
  86. 55 0
      plc调度节点/system/system_communication.h
  87. 645 0
      plc调度节点/system/system_executor.cpp
  88. 110 0
      plc调度节点/system/system_executor.h
  89. 193 0
      plc调度节点/task/task_base.cpp
  90. 163 0
      plc调度节点/task/task_base.h
  91. 80 0
      plc调度节点/task/task_base.puml
  92. 56 0
      plc调度节点/task/task_command_manager.cpp
  93. 42 0
      plc调度节点/task/task_command_manager.h
  94. 12 0
      plc调度节点/task/task_command_manager.puml
  95. 33 0
      plc调度节点/tool/TaskQueue/BaseTask.cpp
  96. 29 0
      plc调度节点/tool/TaskQueue/BaseTask.h
  97. 23 0
      plc调度节点/tool/TaskQueue/TQFactory.cpp
  98. 24 0
      plc调度节点/tool/TaskQueue/TQFactory.h
  99. 58 0
      plc调度节点/tool/TaskQueue/TQInterface.h
  100. 0 0
      plc调度节点/tool/TaskQueue/TaskPool.h

+ 65 - 0
README.md

@@ -0,0 +1,65 @@
+# 1,简介
+    消息服务器rabbitmq集群:
+    ip:   端口:
+    ip:   端口:
+    数据库集群:
+    
+# 2, 交换机
+    交换机分两个,一个负责对接流程消息队列,一个对接各个节点的状态,在服务器提前搭建。
+    
+| 交换机    | 名称         |
+|--------|------------| 
+| 指令交换机  | command_ex |
+| 状态交换机  | statu_ex   |
+
+###     command_ex 指令交换机端口说明:
+| 端口名                         | 发送消息说明      |
+|-----------------------------|-------------|
+| park_command_port           | 停车指令端口      |
+| pick_command_port           | 取车指令端口      |
+| park_response_N_port        | n号终端停车指令反馈  |
+| in_mcpu_response_N_port     |入口N号单片机反馈|
+| out_mcpu_response_N_port    |出口N号单片机反馈|
+| pick_response_N_port        | n号终端取车指令反馈  |
+| command_enqueue_port        | 指令入队端口      |
+| count_command_signal_N_port | N单元指令计数信号端口 |
+| request_command_port        | 请求指令端口      |
+| post_command_N_port         | 向N单元推送指令端口  |
+| command_completed_port      | 指令完成端口      |
+
+
+###     statu_ex 指令交换机端口说明:
+    各个节点向statu_ex交换机发送自身状态,端口名为节点名称+"_statu_port"
+| 端口名                   | 对应节点              |
+|-----------------------|-------------------|
+| in_mcpu_N_statu_port  | 入口N号单片机           |
+| out_mcpu_N_statu_port | 出口N号单片机           |
+| measure_N_statu_port  | N号测量节点            |
+| dispatch_N_statu_port | N单元调度节点           |
+| out_mcpu_N_port       | 出口单片机端口,车辆离开后发送表单 |
+
+# 3,队列
+    队列名称与交换机端口名保存一致,去掉port,增加queue,如:端口名称park_command_port,对应队列名称park_command_queue
+    状态消息对应的队列全部由接收端临时创建,临时对接。
+    open_door_1_queue为出口单片机靠门请求队列,绑定command_completed_port(plc完成端口)
+
+# 4,数据库表
+    1,车位表 space
+        属性:id,楼层(int floor),层内编号(int subID),高度等级(int height_grade),
+            所停车辆车牌(varchar car_number),(int unit)单元号
+    2,车辆表 vehicle
+        属性:车牌号(varchar car_number),唯一码(凭证号)(varchar primary_key),
+            实际测量数据(varchar  actually_measure_info)
+    3, 记录表 record
+       属性:唯一码(凭证号)(varchar primary_key),车牌号(varchar car_number),入场时间(datatime in_time),
+            所停车位id(int space_id),出场时间(datatime out_time)
+
+    4,单元指令队列表 command_queue
+        属性:车牌号(varchar car_number),唯一码(varchar primary_key),单元号(int uint_id),排队编号(int queue_id),
+            停车还是取车(int type),车位信息(varchar space_info),
+            测量信息(取车指令填空)(varchar measure_info), 取车指令出口ID(int export_id)
+    5,单元指令编号时间表 queue_number_data
+        属性:单元号(int unit),最后编号(int,last_number),最后编号时间(datatime input_time)
+
+
+

+ 158 - 0
keepalive+nginx服务部署ubuntu20.04.txt

@@ -0,0 +1,158 @@
+
+1,系统环境
+    两台Ubuntu20.04主机
+    假设ip分别为:192.168.2.100 和 192.168.2.200
+2,安装nginx
+    sudo apt-get install nginx
+    测试是否安装成功的命令:sudo nginx -t
+    也可以在浏览器中输入ip地址,可以看到nignx的页面
+
+    nginx一些相关命令:
+    # 下面两句的效果一样,都是重启
+    sudo service nginx restart
+    sudo systemctl restart nginx
+    # 查询nginx进程号
+    ps -ef |grep nginx
+    # 以下都可以停止进程
+    #nginx从容停止命令,等待所有请求结束后关闭服务
+    sudo kill -QUIT nginx主进程号
+    # 快速停止命令,立即关闭nginx进程
+    sudo kill -TERM nginx主进程号
+    # 以上两个停止命令如果不管用,可以强制停止
+    sudo kill -9 nginx主进程号
+    # 删除nginx,-purge包括配置文件
+    sudo apt-get --purge remove nginx
+
+2,修改nginx默认web服务的端口,两台主机均需修改
+    nginx默认配置文件是/etc/nginx/sites-enabled/default,默认端口为80
+    可修改其端口(修改其端口是为了不让该服务占用80端口,实际项目上使用的时候也需要改端口)
+    sudo gedit /etc/nginx/sites-enabled/default
+    将 listen 80 default server;
+    与 listen [::] 80 default server;两行中的80改为想修改的端口即可,本例以修改为81为例。
+    保存修改后的文件,重启nginx服务:
+    sudo systemctl restart nginx 重启后网页访问nginx原来的80端口会无法访问,新修改后的端口可以访问
+
+3, 修改nginx的默认页面,做上标记,便于区分,两台主机均需修改
+    sudo gedit /var/www/html/index.nginx-debian.html
+    在<p><em>Thank you for using nginx.</em></p>这行下面加入:
+    <p>I come from Ubuntu server:192.168.2.100</p>
+    192.168.2.200的主机加入时文本中的IP地址改成自己的ip地址即可
+    保存关闭分别检查
+    在192.168.2.100的主机浏览器中输入 192.168.2.100:81 即可看到刚出添加的文。192.168.2.200的主机同理
+
+4,配置负载均衡,两台主机均需相同操作
+    在129.168.2.100服务器上配置负载均衡。
+    有关负载均衡方法的说明,可参考:https://www.cnblogs.com/1214804270hacker/p/9325150.html
+    sudo /etc/nginx/conf.d/nginx.conf
+    填写内容如下:
+        upstream text_nginx {
+         #负载均衡方法,可选:least_conn,ip_hash等,不填写则为轮询方式;
+         # 服务器的访问地址,最好使用服务器的私有IP以获得更好的性能和安全性。
+         server 192.168.2.100:81 weight=1;
+         server 192.168.2.200:81 weight=2;
+    }
+    server {
+            # 负载均衡的监听端口
+            listen 80 default_server;
+            listen [::]:80 default_server;
+            # 负载均衡服务器的服务名称,没有时填写 _
+            server_name _;
+
+            location / {
+                    # 代理转发,注意这个text_nginx要与 upstream 后的字符串相同
+                    proxy_pass http://text_nginx;
+            }
+    }
+    保存后重启nginx服务。
+    sudo systemctl restart nginx
+5, 测试负载均衡
+    在浏览器中输入192.168.2.100,刷新页面后发现来自 192.168.2.100服务器的页面和来自192.168.2.200服务器的页面轮番出现,
+    且200页面出现的概率是100页面的两倍(填写两个服务器权重的时候,weight值不同)。
+
+6,安装配置keepalived,两台主机均需相同操作
+    命令安装:sudo apt-get install keepalived
+    设置随系统自启动:sudo gedit /etc/rc.local 在文件中添加以下内容:
+    #!/bin/sh -e
+    # 服务类要以 & 结尾一行,表示不要等待运行结束
+    service keepalived start &
+    #文末必须以exit 0结束
+    exit 0
+    配置keepalived命令:sudo gedit /etc/keepalived/keepalived.conf  在文件中加入以下内容:
+        global_defs {
+       router_id lb01 #路由id号,不可重复
+    }
+    #预先定义一个脚本,方便后面调用,也可定义多个,方便选择
+    vrrp_script chk_nginx {
+        script "/etc/keepalived/nginx_chk.sh"  #脚本具体路径
+        interval 2     #脚本运行间隔。单位s
+    }
+    vrrp_instance VI_1{ #定义一个实例
+        state MASTER    #MASTER为主节点、BACKUP为备用节点  只是说明,具体根据优先级
+        interface ens1  #虚拟IP地址放置的网卡位置
+        virtual_router_id 51  #当前虚拟路由唯一标识,同一个集群id需要一致,范围0-255
+        priority 101    #当前节点在虚拟路由中的优先级,值越大优先级越大;范围1-254
+        advert_int 1    #主备通讯间隔
+        authentication {
+            auth_type PASS
+            auth_pass 123456    #认证号,集群中需要一致
+        }
+        virtual_ipaddress {
+            192.168.2.130 #使用的虚拟IP,不能和网段内IP冲突
+        }
+        #使用在这个域中预先定义的脚本,上面定义的
+        track_script {
+            chk_nginx
+        }
+    }
+
+    注意:192.168.2.200主机上router_id不可相同,MASTER需要改为BACKUP
+
+    创建nginx_chk脚本
+    脚本文件/etc/keepalived/nginx_chk.sh用于检查nginx相关服务器是否启动,如果没有启动则重启。如果重启不成功,则杀死keepalived服务,切换到备用服务
+    sudo gedit /etc/keepalived/nginx_chk.sh  添加以下内容:
+    #!/bin/bash
+    #检查是否有nginx相关的进程
+    A=`ps -C nginx --no-header |wc -l`
+    #如果没有
+    if [ $A -eq 0 ];then
+        # 重启nginx,延迟2秒
+        service nginx restart
+        sleep 2
+        # 重新检查是否有nginx相关的进程
+        if [ `ps -C nginx --no-header |wc -l` -eq 0 ];then
+            # 仍然没有nginx相关的进程,杀死当前keepalived,切换到备用机
+            killall keepalived
+        fi
+    fi
+
+    为脚本文件添加执行权限:sudo chmod +x /etc/keepalived/nginx_chk.sh
+    两台服务器都要添加这个脚本和权限。
+7,重启keepalived
+    sudo service keepalived restart
+5,测试
+    在192.168.2.100(MASTER)节点上执行:ip a
+    如果前面顺利,这里可以看到设置的虚拟ip
+    192.168.2.200(BACKUP)上没有虚拟IP
+    停掉192.168.2.100(MASTER)的keepalived
+    sudo service keepalived stop
+    再到192.168.2.200(BACKUP)上执行:ip a
+    可以看到虚拟IP说明配置成功
+
+    检查页面能否访问
+    先将上面停掉的master上的keepalived启动起来:sudo service keepalived start
+    通过浏览器访问虚拟IP 192.168.2.130
+    一直刷新能访问到不断切换的两个页面则高可用性负载均衡配置成功
+
+参考
+https://blog.csdn.net/weixin_41621706/article/details/117173069
+https://blog.csdn.net/weixin_41621706/article/details/117217349
+
+
+
+
+
+
+
+
+
+

+ 148 - 0
message.proto

@@ -0,0 +1,148 @@
+syntax = "proto3";
+
+/*测量信息*/
+message measure_info {
+  float cx=1;
+  float cy=2;
+  float theta=3;
+  float length=4;
+  float width=5;
+  float height=6;
+  float wheelbase=7;
+  float front_theta=8;
+  int32 border_statu=9;
+  int32 ground_status=10;                   //0  ok 1,nothing 2,noise  3,border
+}
+
+/*分配的车位信息*/
+message parkspace_info{
+  int32 id=1;
+  int32 unit_id=2;  //单元号
+  int32 floor=3;    //楼层号
+  int32 room_id=4;    //同层编号
+}
+
+enum STATU{
+  eNormal=0;
+  eError=1;
+}
+
+/*
+表单执行状态
+ */
+message table_statu{
+  STATU execute_statu=1;    //执行状态
+  string statu_description=2; //状态描述
+}
+
+/*
+停车表单
+ */
+message park_table{
+  table_statu statu=1;  //表单状态
+  int32 queue_id=2;        //指令排队编号
+
+  string car_number=3;
+  int32 unit_id=4;
+  int32 terminal_id=5;
+  string primary_key=6;
+
+  measure_info entrance_measure_info=7;   //入口测量信息
+
+
+  parkspace_info allocated_space_info=8;       //分配的车位信息
+
+  measure_info actually_measure_info=9;   //实际测量信息或者叫二次测量信息
+
+  parkspace_info actually_space_info=10;      //实际停放的车位
+
+
+}
+
+/*
+取车表单
+ */
+message pick_table{
+  table_statu statu=1;  //表单状态
+  int32 queue_id=2;        //指令排队编号
+
+  string car_number=3;
+  int32 unit_id=4;
+  int32 terminal_id=5;
+  string primary_key=6;
+
+  parkspace_info actually_space_info=7; //实际停放的车位信息
+
+  measure_info actually_measure_info=8; //存车时的实际测量信息(轴距)
+
+  int32 export_id=9;            //分配出口
+  bool  is_leaved=10;         //是否离开
+
+
+}
+
+
+
+/*
+以下是状态消息
+ */
+
+/*
+单片机节点状态
+ */
+message out_mcpu_statu{     //数值+1后
+  int32 door_statu=1;       //外门状态       0无效, 1无效, 2开到位, 3 关到位, 4开关中, 5 故障
+  int32 outside_safety=2;    //是否有车      0无效, 1无车, 2有车
+}
+
+message in_mcpu_statu{      //数值+1后
+  int32 door_statu=1;       //外门状态       0无效, 1无效, 2开到位, 3 关到位, 4开关中, 5 故障
+  int32 back_io=2;          //后超界       0无效, 1后超界, 2正常
+  int32 is_occupy=3;        //是否有车      0无效, 1无车, 2有车
+  int32 heighth=4;          //车高状态      0无效, 1无效, 2小车, 3中车, 4大车, 5故障, 6故障
+}
+/*
+测量节点状态
+ */
+message measure_statu{
+  measure_info info=1;
+}
+
+//搬运器状态枚举
+enum CarrierStatu{
+  eIdle=0;
+  eBusy=1;
+  eFault=2;
+}
+
+//调度入口汽车范围的修正信息
+message dispatch_region_info
+{
+    int32 terminal_id=1;                //入口终端编号, 1~6
+    float turnplate_angle_min=2;        //转盘角度最小值, 负值, 例如 -5度
+    float turnplate_angle_max=3;        //转盘角度最大值, 正值, 例如 +5度
+}
+
+/*
+搬运器状态消息
+ */
+message dispatch_node_statu{
+  CarrierStatu statu=1;
+  int32 idle_stop_floor=2;  //空闲时停留位置
+  park_table  running_pack_info=3;  //正在执行的停车表单
+  pick_table  running_pick_info=4;  //正在执行的取车表单
+
+    int32                                   unit_id = 5;                            //单元号, 1~3
+    int32                                   plc_heartbeat = 6;                      //plc心跳信息
+    int32                                   plc_status_info = 7;                    //plc状态的集合
+                                                                                    		//0 bit, 手动模式
+                                                                                    		//1 bit, 自动模式
+                                                                                    		//2 bit, 自动运行中
+                                                                                    		//3 bit, 复位
+                                                                                    		//4 bit, 1号口可以进车
+                                                                                    		//5 bit, 2号口可以进车
+                                                                                    		//6 bit, 预留
+                                                                                    		//7 bit, 预留
+    repeated dispatch_region_info           dispatch_region_info_vector = 8;        //调度入口汽车范围的修正信息
+
+}

+ 113 - 0
plc调度节点/CMakeLists.txt

@@ -0,0 +1,113 @@
+project(nnxx_tests)
+
+cmake_minimum_required(VERSION 3.5)
+
+set (CMAKE_CXX_STANDARD 11)
+
+find_package(PkgConfig REQUIRED)
+pkg_check_modules(nanomsg REQUIRED nanomsg)
+FIND_PACKAGE(Protobuf REQUIRED)
+FIND_PACKAGE(Glog REQUIRED)
+#FIND_PACKAGE(OpenCV REQUIRED)
+#FIND_PACKAGE(PCL REQUIRED)
+
+
+MESSAGE(WARN "pcl:: ${PCL_INCLUDE_DIRS} --- ${PCL_LIBRARIES}")
+include_directories(
+		/usr/include
+		/usr/local/include
+		/usr/local/include/cppconn/
+#		/usr/local/mysql/connector-c++-8.0.30/include
+		/usr/local/include/snap7
+#        ${PCL_INCLUDE_DIRS}
+#        ${OpenCV_INCLUDE_DIRS}
+        ${PROTOBUF_INCLUDE_DIRS}
+        laser
+        Locate
+        communication
+        message
+        error_code
+        tool
+		system
+		dispatch
+		rabbimq
+#		parkspace_allocation
+)
+link_directories("/usr/local/lib"  "/usr/local/mysql/connector-c++-8.0.30/lib64/debug")
+
+message(STATUS ${EXECUTABLE_OUTPUT_PATH})
+
+
+aux_source_directory(${CMAKE_CURRENT_LIST_DIR}/error_code error_src )
+aux_source_directory(${CMAKE_CURRENT_LIST_DIR}/message message_src )
+aux_source_directory(${CMAKE_CURRENT_LIST_DIR}/lidar_locate locate_src )
+#aux_source_directory(${CMAKE_CURRENT_LIST_DIR}/robot robot_src )
+aux_source_directory(${CMAKE_CURRENT_LIST_DIR}/laser LASER_SRC )
+#aux_source_directory(${CMAKE_CURRENT_LIST_DIR}/plc PLC_SRC )
+aux_source_directory(${CMAKE_CURRENT_LIST_DIR}/locate LOCATE_SRC )
+aux_source_directory(${CMAKE_CURRENT_LIST_DIR}/terminor TERMINOR_SRC )
+aux_source_directory(${CMAKE_CURRENT_LIST_DIR}/task TASK_MANAGER_SRC )
+aux_source_directory(${CMAKE_CURRENT_LIST_DIR}/tool TOOL_SRC )
+aux_source_directory(${CMAKE_CURRENT_LIST_DIR}/tool/TaskQueue TASK_QUEUE_SRC )
+aux_source_directory(${CMAKE_CURRENT_LIST_DIR}/communication COMMUNICATION_SRC )
+aux_source_directory(${CMAKE_CURRENT_LIST_DIR}/system SYSTEM_SRC )
+aux_source_directory(${CMAKE_CURRENT_LIST_DIR}/dispatch DISPATCH_SRC )
+aux_source_directory(${CMAKE_CURRENT_LIST_DIR}/snap7_communication SNAP7_COMMUNICATION_SRC )
+aux_source_directory(${CMAKE_CURRENT_LIST_DIR}/rabbitmq RABBITMQ_SRC )
+
+#aux_source_directory(${CMAKE_CURRENT_LIST_DIR}/parkspace_allocation PARKSPACE_ALLOCATION_SRC )
+
+add_executable(terminal
+        main.cpp
+        ${error_src}
+        ${locate_src}
+        ${robot_src}
+        ${message_src}
+
+        ${LASER_SRC}
+        ${PLC_SRC}
+        ${TERMINOR_SRC}
+        ${LOCATE_SRC}
+        ${TASK_MANAGER_SRC}
+		${TOOL_SRC}
+		${TASK_QUEUE_SRC}
+		${COMMUNICATION_SRC}
+		${SNAP7_COMMUNICATION_SRC}
+        ${SYSTEM_SRC}
+		${DISPATCH_SRC}
+		${RABBITMQ_SRC}
+#		${PARKSPACE_ALLOCATION_SRC}
+
+		)
+
+
+
+target_link_libraries(terminal
+        /usr/local/lib/libglog.a
+        /usr/local/lib/libgflags.a
+#        /usr/local/lib/liblivox_sdk_static.a
+#        /usr/local/apr/lib/libapr-1.a
+        nnxx
+        nanomsg
+
+		rabbitmq
+		libmysqlcppconn.so
+#		MySQL::conncpp
+#		conncpp
+#		connector
+#		mysqlcppconn8
+
+
+        ${PROTOBUF_LIBRARIES}
+#        ${OpenCV_LIBS}
+        ${GLOG_LIBRARIES}
+#        ${PCL_LIBRARIES}
+        ${PROTOBUF_LIBRARIES}
+
+#        libtensorflow_cc.so
+        #tf_3dcnn_api.so
+#        pointSIFT_API.so
+		snap7
+        -lpthread
+        )
+

+ 60 - 0
plc调度节点/README.md

@@ -0,0 +1,60 @@
+# 1,功能描述
+    调度负责配合plc, 执行存车取车的指令
+
+    维护数据库
+        commmand_queue              指令表
+        space                       车位表
+        vehicle                     车辆表
+    接受rabbitmq 状态信息
+        in_mcpu_N_statu_port        入口单片机
+        out_mcpu_N_statu_port       出口单片机
+        measure_N_statu_port        感测雷达
+    发送rabbitmq 状态信息
+        dispatch_N_statu_port       调度
+
+
+# 2,流程介绍:
+a,  周期性 查询数据库 command_queue 指令表
+    如果有状态为0(排队中)的指令, 选取最优解,
+    并执行
+b1, 存车指令, 查询 space表, 找到合适的空闲车位, 并写入车牌号 表示占有该车位
+    将车位信息 填充到 command_queue 指令表, 并将状态改为1(工作中)
+    生成 park_table 存车表单 交给 plc执行
+    plc执行完成后, 清除存车指令 command_queue, 并保存车辆信息到 vehicle
+b2, 取车指令, 查询 vehicle表, 找到之前保存的感测信息, 查询空闲出口id
+    将感测信息和出口id 填充到 command_queue 指令表, 并将状态改为1(工作中)
+    生成 pick_table 取车表单 交给 plc执行
+    plc执行完成后, 修改 command_queue表, 指令状态写2 ,
+    清除 车辆信息到 vehicle, 清除车位信息 space,
+
+
+# 3,使用平台:
+    linux x64 / linux-arm
+# 4,业务逻辑
+# 5,编译
+    cd xxx/plc调度节点
+    ./proto.sh
+    mkdir ./build
+    cd ./build
+    cmake ..
+    make
+# 6,运行
+    指定运行调度单元
+    cd xxx/plc调度节点/build
+    开3个终端界面
+    ./terminal 0
+    ./terminal 1
+    ./terminal 2
+
+    一键运行所有单元
+    cd xxx/plc调度节点
+    ./run_dispatch.sh
+
+# 7,部署
+    依赖三方库
+    rabbitmq
+    protobuf
+    mysql cpp connect 1.1
+    glog
+    gflag
+    snap7

+ 729 - 0
plc调度节点/communication/communication.pb.cc

@@ -0,0 +1,729 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: communication.proto
+
+#include "communication.pb.h"
+
+#include <algorithm>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/port.h>
+#include <google/protobuf/stubs/once.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/wire_format_lite_inl.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/generated_message_reflection.h>
+#include <google/protobuf/reflection_ops.h>
+#include <google/protobuf/wire_format.h>
+// This is a temporary google only hack
+#ifdef GOOGLE_PROTOBUF_ENFORCE_UNIQUENESS
+#include "third_party/protobuf/version.h"
+#endif
+// @@protoc_insertion_point(includes)
+namespace Communication_proto {
+class Communication_parameterDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<Communication_parameter>
+      _instance;
+} _Communication_parameter_default_instance_;
+class Communication_parameter_allDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<Communication_parameter_all>
+      _instance;
+} _Communication_parameter_all_default_instance_;
+}  // namespace Communication_proto
+namespace protobuf_communication_2eproto {
+void InitDefaultsCommunication_parameterImpl() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+#ifdef GOOGLE_PROTOBUF_ENFORCE_UNIQUENESS
+  ::google::protobuf::internal::InitProtobufDefaultsForceUnique();
+#else
+  ::google::protobuf::internal::InitProtobufDefaults();
+#endif  // GOOGLE_PROTOBUF_ENFORCE_UNIQUENESS
+  {
+    void* ptr = &::Communication_proto::_Communication_parameter_default_instance_;
+    new (ptr) ::Communication_proto::Communication_parameter();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::Communication_proto::Communication_parameter::InitAsDefaultInstance();
+}
+
+void InitDefaultsCommunication_parameter() {
+  static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
+  ::google::protobuf::GoogleOnceInit(&once, &InitDefaultsCommunication_parameterImpl);
+}
+
+void InitDefaultsCommunication_parameter_allImpl() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+#ifdef GOOGLE_PROTOBUF_ENFORCE_UNIQUENESS
+  ::google::protobuf::internal::InitProtobufDefaultsForceUnique();
+#else
+  ::google::protobuf::internal::InitProtobufDefaults();
+#endif  // GOOGLE_PROTOBUF_ENFORCE_UNIQUENESS
+  protobuf_communication_2eproto::InitDefaultsCommunication_parameter();
+  {
+    void* ptr = &::Communication_proto::_Communication_parameter_all_default_instance_;
+    new (ptr) ::Communication_proto::Communication_parameter_all();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::Communication_proto::Communication_parameter_all::InitAsDefaultInstance();
+}
+
+void InitDefaultsCommunication_parameter_all() {
+  static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
+  ::google::protobuf::GoogleOnceInit(&once, &InitDefaultsCommunication_parameter_allImpl);
+}
+
+::google::protobuf::Metadata file_level_metadata[2];
+
+const ::google::protobuf::uint32 TableStruct::offsets[] GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
+  GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::Communication_proto::Communication_parameter, _has_bits_),
+  GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::Communication_proto::Communication_parameter, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::Communication_proto::Communication_parameter, bind_string_),
+  GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::Communication_proto::Communication_parameter, connect_string_vector_),
+  0,
+  ~0u,
+  GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::Communication_proto::Communication_parameter_all, _has_bits_),
+  GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::Communication_proto::Communication_parameter_all, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::Communication_proto::Communication_parameter_all, communication_parameters_),
+  0,
+};
+static const ::google::protobuf::internal::MigrationSchema schemas[] GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
+  { 0, 7, sizeof(::Communication_proto::Communication_parameter)},
+  { 9, 15, sizeof(::Communication_proto::Communication_parameter_all)},
+};
+
+static ::google::protobuf::Message const * const file_default_instances[] = {
+  reinterpret_cast<const ::google::protobuf::Message*>(&::Communication_proto::_Communication_parameter_default_instance_),
+  reinterpret_cast<const ::google::protobuf::Message*>(&::Communication_proto::_Communication_parameter_all_default_instance_),
+};
+
+void protobuf_AssignDescriptors() {
+  AddDescriptors();
+  ::google::protobuf::MessageFactory* factory = NULL;
+  AssignDescriptors(
+      "communication.proto", schemas, file_default_instances, TableStruct::offsets, factory,
+      file_level_metadata, NULL, NULL);
+}
+
+void protobuf_AssignDescriptorsOnce() {
+  static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
+  ::google::protobuf::GoogleOnceInit(&once, &protobuf_AssignDescriptors);
+}
+
+void protobuf_RegisterTypes(const ::std::string&) GOOGLE_PROTOBUF_ATTRIBUTE_COLD;
+void protobuf_RegisterTypes(const ::std::string&) {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::internal::RegisterAllTypes(file_level_metadata, 2);
+}
+
+void AddDescriptorsImpl() {
+  InitDefaults();
+  static const char descriptor[] GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
+      "\n\023communication.proto\022\023Communication_pro"
+      "to\"M\n\027Communication_parameter\022\023\n\013bind_st"
+      "ring\030\001 \001(\t\022\035\n\025connect_string_vector\030\002 \003("
+      "\t\"m\n\033Communication_parameter_all\022N\n\030comm"
+      "unication_parameters\030\001 \001(\0132,.Communicati"
+      "on_proto.Communication_parameter"
+  };
+  ::google::protobuf::DescriptorPool::InternalAddGeneratedFile(
+      descriptor, 232);
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
+    "communication.proto", &protobuf_RegisterTypes);
+}
+
+void AddDescriptors() {
+  static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
+  ::google::protobuf::GoogleOnceInit(&once, &AddDescriptorsImpl);
+}
+// Force AddDescriptors() to be called at dynamic initialization time.
+struct StaticDescriptorInitializer {
+  StaticDescriptorInitializer() {
+    AddDescriptors();
+  }
+} static_descriptor_initializer;
+}  // namespace protobuf_communication_2eproto
+namespace Communication_proto {
+
+// ===================================================================
+
+void Communication_parameter::InitAsDefaultInstance() {
+}
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int Communication_parameter::kBindStringFieldNumber;
+const int Communication_parameter::kConnectStringVectorFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+Communication_parameter::Communication_parameter()
+  : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+  if (GOOGLE_PREDICT_TRUE(this != internal_default_instance())) {
+    ::protobuf_communication_2eproto::InitDefaultsCommunication_parameter();
+  }
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:Communication_proto.Communication_parameter)
+}
+Communication_parameter::Communication_parameter(const Communication_parameter& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(NULL),
+      _has_bits_(from._has_bits_),
+      _cached_size_(0),
+      connect_string_vector_(from.connect_string_vector_) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  bind_string_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (from.has_bind_string()) {
+    bind_string_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.bind_string_);
+  }
+  // @@protoc_insertion_point(copy_constructor:Communication_proto.Communication_parameter)
+}
+
+void Communication_parameter::SharedCtor() {
+  _cached_size_ = 0;
+  bind_string_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+
+Communication_parameter::~Communication_parameter() {
+  // @@protoc_insertion_point(destructor:Communication_proto.Communication_parameter)
+  SharedDtor();
+}
+
+void Communication_parameter::SharedDtor() {
+  bind_string_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+
+void Communication_parameter::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* Communication_parameter::descriptor() {
+  ::protobuf_communication_2eproto::protobuf_AssignDescriptorsOnce();
+  return ::protobuf_communication_2eproto::file_level_metadata[kIndexInFileMessages].descriptor;
+}
+
+const Communication_parameter& Communication_parameter::default_instance() {
+  ::protobuf_communication_2eproto::InitDefaultsCommunication_parameter();
+  return *internal_default_instance();
+}
+
+Communication_parameter* Communication_parameter::New(::google::protobuf::Arena* arena) const {
+  Communication_parameter* n = new Communication_parameter;
+  if (arena != NULL) {
+    arena->Own(n);
+  }
+  return n;
+}
+
+void Communication_parameter::Clear() {
+// @@protoc_insertion_point(message_clear_start:Communication_proto.Communication_parameter)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  connect_string_vector_.Clear();
+  cached_has_bits = _has_bits_[0];
+  if (cached_has_bits & 0x00000001u) {
+    GOOGLE_DCHECK(!bind_string_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()));
+    (*bind_string_.UnsafeRawStringPointer())->clear();
+  }
+  _has_bits_.Clear();
+  _internal_metadata_.Clear();
+}
+
+bool Communication_parameter::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:Communication_proto.Communication_parameter)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // optional string bind_string = 1;
+      case 1: {
+        if (static_cast< ::google::protobuf::uint8>(tag) ==
+            static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_bind_string()));
+          ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+            this->bind_string().data(), static_cast<int>(this->bind_string().length()),
+            ::google::protobuf::internal::WireFormat::PARSE,
+            "Communication_proto.Communication_parameter.bind_string");
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // repeated string connect_string_vector = 2;
+      case 2: {
+        if (static_cast< ::google::protobuf::uint8>(tag) ==
+            static_cast< ::google::protobuf::uint8>(18u /* 18 & 0xFF */)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->add_connect_string_vector()));
+          ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+            this->connect_string_vector(this->connect_string_vector_size() - 1).data(),
+            static_cast<int>(this->connect_string_vector(this->connect_string_vector_size() - 1).length()),
+            ::google::protobuf::internal::WireFormat::PARSE,
+            "Communication_proto.Communication_parameter.connect_string_vector");
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:Communication_proto.Communication_parameter)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:Communication_proto.Communication_parameter)
+  return false;
+#undef DO_
+}
+
+void Communication_parameter::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:Communication_proto.Communication_parameter)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  cached_has_bits = _has_bits_[0];
+  // optional string bind_string = 1;
+  if (cached_has_bits & 0x00000001u) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->bind_string().data(), static_cast<int>(this->bind_string().length()),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "Communication_proto.Communication_parameter.bind_string");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      1, this->bind_string(), output);
+  }
+
+  // repeated string connect_string_vector = 2;
+  for (int i = 0, n = this->connect_string_vector_size(); i < n; i++) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->connect_string_vector(i).data(), static_cast<int>(this->connect_string_vector(i).length()),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "Communication_proto.Communication_parameter.connect_string_vector");
+    ::google::protobuf::internal::WireFormatLite::WriteString(
+      2, this->connect_string_vector(i), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:Communication_proto.Communication_parameter)
+}
+
+::google::protobuf::uint8* Communication_parameter::InternalSerializeWithCachedSizesToArray(
+    bool deterministic, ::google::protobuf::uint8* target) const {
+  (void)deterministic; // Unused
+  // @@protoc_insertion_point(serialize_to_array_start:Communication_proto.Communication_parameter)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  cached_has_bits = _has_bits_[0];
+  // optional string bind_string = 1;
+  if (cached_has_bits & 0x00000001u) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->bind_string().data(), static_cast<int>(this->bind_string().length()),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "Communication_proto.Communication_parameter.bind_string");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        1, this->bind_string(), target);
+  }
+
+  // repeated string connect_string_vector = 2;
+  for (int i = 0, n = this->connect_string_vector_size(); i < n; i++) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->connect_string_vector(i).data(), static_cast<int>(this->connect_string_vector(i).length()),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "Communication_proto.Communication_parameter.connect_string_vector");
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteStringToArray(2, this->connect_string_vector(i), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:Communication_proto.Communication_parameter)
+  return target;
+}
+
+size_t Communication_parameter::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:Communication_proto.Communication_parameter)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  // repeated string connect_string_vector = 2;
+  total_size += 1 *
+      ::google::protobuf::internal::FromIntSize(this->connect_string_vector_size());
+  for (int i = 0, n = this->connect_string_vector_size(); i < n; i++) {
+    total_size += ::google::protobuf::internal::WireFormatLite::StringSize(
+      this->connect_string_vector(i));
+  }
+
+  // optional string bind_string = 1;
+  if (has_bind_string()) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->bind_string());
+  }
+
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = cached_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void Communication_parameter::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:Communication_proto.Communication_parameter)
+  GOOGLE_DCHECK_NE(&from, this);
+  const Communication_parameter* source =
+      ::google::protobuf::internal::DynamicCastToGenerated<const Communication_parameter>(
+          &from);
+  if (source == NULL) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:Communication_proto.Communication_parameter)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:Communication_proto.Communication_parameter)
+    MergeFrom(*source);
+  }
+}
+
+void Communication_parameter::MergeFrom(const Communication_parameter& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:Communication_proto.Communication_parameter)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  connect_string_vector_.MergeFrom(from.connect_string_vector_);
+  if (from.has_bind_string()) {
+    set_has_bind_string();
+    bind_string_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.bind_string_);
+  }
+}
+
+void Communication_parameter::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:Communication_proto.Communication_parameter)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void Communication_parameter::CopyFrom(const Communication_parameter& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:Communication_proto.Communication_parameter)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool Communication_parameter::IsInitialized() const {
+  return true;
+}
+
+void Communication_parameter::Swap(Communication_parameter* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void Communication_parameter::InternalSwap(Communication_parameter* other) {
+  using std::swap;
+  connect_string_vector_.InternalSwap(&other->connect_string_vector_);
+  bind_string_.Swap(&other->bind_string_);
+  swap(_has_bits_[0], other->_has_bits_[0]);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata Communication_parameter::GetMetadata() const {
+  protobuf_communication_2eproto::protobuf_AssignDescriptorsOnce();
+  return ::protobuf_communication_2eproto::file_level_metadata[kIndexInFileMessages];
+}
+
+
+// ===================================================================
+
+void Communication_parameter_all::InitAsDefaultInstance() {
+  ::Communication_proto::_Communication_parameter_all_default_instance_._instance.get_mutable()->communication_parameters_ = const_cast< ::Communication_proto::Communication_parameter*>(
+      ::Communication_proto::Communication_parameter::internal_default_instance());
+}
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int Communication_parameter_all::kCommunicationParametersFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+Communication_parameter_all::Communication_parameter_all()
+  : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+  if (GOOGLE_PREDICT_TRUE(this != internal_default_instance())) {
+    ::protobuf_communication_2eproto::InitDefaultsCommunication_parameter_all();
+  }
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:Communication_proto.Communication_parameter_all)
+}
+Communication_parameter_all::Communication_parameter_all(const Communication_parameter_all& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(NULL),
+      _has_bits_(from._has_bits_),
+      _cached_size_(0) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  if (from.has_communication_parameters()) {
+    communication_parameters_ = new ::Communication_proto::Communication_parameter(*from.communication_parameters_);
+  } else {
+    communication_parameters_ = NULL;
+  }
+  // @@protoc_insertion_point(copy_constructor:Communication_proto.Communication_parameter_all)
+}
+
+void Communication_parameter_all::SharedCtor() {
+  _cached_size_ = 0;
+  communication_parameters_ = NULL;
+}
+
+Communication_parameter_all::~Communication_parameter_all() {
+  // @@protoc_insertion_point(destructor:Communication_proto.Communication_parameter_all)
+  SharedDtor();
+}
+
+void Communication_parameter_all::SharedDtor() {
+  if (this != internal_default_instance()) delete communication_parameters_;
+}
+
+void Communication_parameter_all::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* Communication_parameter_all::descriptor() {
+  ::protobuf_communication_2eproto::protobuf_AssignDescriptorsOnce();
+  return ::protobuf_communication_2eproto::file_level_metadata[kIndexInFileMessages].descriptor;
+}
+
+const Communication_parameter_all& Communication_parameter_all::default_instance() {
+  ::protobuf_communication_2eproto::InitDefaultsCommunication_parameter_all();
+  return *internal_default_instance();
+}
+
+Communication_parameter_all* Communication_parameter_all::New(::google::protobuf::Arena* arena) const {
+  Communication_parameter_all* n = new Communication_parameter_all;
+  if (arena != NULL) {
+    arena->Own(n);
+  }
+  return n;
+}
+
+void Communication_parameter_all::Clear() {
+// @@protoc_insertion_point(message_clear_start:Communication_proto.Communication_parameter_all)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  cached_has_bits = _has_bits_[0];
+  if (cached_has_bits & 0x00000001u) {
+    GOOGLE_DCHECK(communication_parameters_ != NULL);
+    communication_parameters_->Clear();
+  }
+  _has_bits_.Clear();
+  _internal_metadata_.Clear();
+}
+
+bool Communication_parameter_all::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:Communication_proto.Communication_parameter_all)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // optional .Communication_proto.Communication_parameter communication_parameters = 1;
+      case 1: {
+        if (static_cast< ::google::protobuf::uint8>(tag) ==
+            static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+               input, mutable_communication_parameters()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:Communication_proto.Communication_parameter_all)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:Communication_proto.Communication_parameter_all)
+  return false;
+#undef DO_
+}
+
+void Communication_parameter_all::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:Communication_proto.Communication_parameter_all)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  cached_has_bits = _has_bits_[0];
+  // optional .Communication_proto.Communication_parameter communication_parameters = 1;
+  if (cached_has_bits & 0x00000001u) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      1, *this->communication_parameters_, output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:Communication_proto.Communication_parameter_all)
+}
+
+::google::protobuf::uint8* Communication_parameter_all::InternalSerializeWithCachedSizesToArray(
+    bool deterministic, ::google::protobuf::uint8* target) const {
+  (void)deterministic; // Unused
+  // @@protoc_insertion_point(serialize_to_array_start:Communication_proto.Communication_parameter_all)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  cached_has_bits = _has_bits_[0];
+  // optional .Communication_proto.Communication_parameter communication_parameters = 1;
+  if (cached_has_bits & 0x00000001u) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        1, *this->communication_parameters_, deterministic, target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:Communication_proto.Communication_parameter_all)
+  return target;
+}
+
+size_t Communication_parameter_all::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:Communication_proto.Communication_parameter_all)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  // optional .Communication_proto.Communication_parameter communication_parameters = 1;
+  if (has_communication_parameters()) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::MessageSize(
+        *this->communication_parameters_);
+  }
+
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = cached_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void Communication_parameter_all::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:Communication_proto.Communication_parameter_all)
+  GOOGLE_DCHECK_NE(&from, this);
+  const Communication_parameter_all* source =
+      ::google::protobuf::internal::DynamicCastToGenerated<const Communication_parameter_all>(
+          &from);
+  if (source == NULL) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:Communication_proto.Communication_parameter_all)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:Communication_proto.Communication_parameter_all)
+    MergeFrom(*source);
+  }
+}
+
+void Communication_parameter_all::MergeFrom(const Communication_parameter_all& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:Communication_proto.Communication_parameter_all)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  if (from.has_communication_parameters()) {
+    mutable_communication_parameters()->::Communication_proto::Communication_parameter::MergeFrom(from.communication_parameters());
+  }
+}
+
+void Communication_parameter_all::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:Communication_proto.Communication_parameter_all)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void Communication_parameter_all::CopyFrom(const Communication_parameter_all& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:Communication_proto.Communication_parameter_all)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool Communication_parameter_all::IsInitialized() const {
+  return true;
+}
+
+void Communication_parameter_all::Swap(Communication_parameter_all* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void Communication_parameter_all::InternalSwap(Communication_parameter_all* other) {
+  using std::swap;
+  swap(communication_parameters_, other->communication_parameters_);
+  swap(_has_bits_[0], other->_has_bits_[0]);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata Communication_parameter_all::GetMetadata() const {
+  protobuf_communication_2eproto::protobuf_AssignDescriptorsOnce();
+  return ::protobuf_communication_2eproto::file_level_metadata[kIndexInFileMessages];
+}
+
+
+// @@protoc_insertion_point(namespace_scope)
+}  // namespace Communication_proto
+
+// @@protoc_insertion_point(global_scope)

+ 530 - 0
plc调度节点/communication/communication.pb.h

@@ -0,0 +1,530 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: communication.proto
+
+#ifndef PROTOBUF_communication_2eproto__INCLUDED
+#define PROTOBUF_communication_2eproto__INCLUDED
+
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+
+#if GOOGLE_PROTOBUF_VERSION < 3005000
+#error This file was generated by a newer version of protoc which is
+#error incompatible with your Protocol Buffer headers.  Please update
+#error your headers.
+#endif
+#if 3005000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
+#error This file was generated by an older version of protoc which is
+#error incompatible with your Protocol Buffer headers.  Please
+#error regenerate this file with a newer version of protoc.
+#endif
+
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/arena.h>
+#include <google/protobuf/arenastring.h>
+#include <google/protobuf/generated_message_table_driven.h>
+#include <google/protobuf/generated_message_util.h>
+#include <google/protobuf/metadata.h>
+#include <google/protobuf/message.h>
+#include <google/protobuf/repeated_field.h>  // IWYU pragma: export
+#include <google/protobuf/extension_set.h>  // IWYU pragma: export
+#include <google/protobuf/unknown_field_set.h>
+// @@protoc_insertion_point(includes)
+
+namespace protobuf_communication_2eproto {
+// Internal implementation detail -- do not use these members.
+struct TableStruct {
+  static const ::google::protobuf::internal::ParseTableField entries[];
+  static const ::google::protobuf::internal::AuxillaryParseTableField aux[];
+  static const ::google::protobuf::internal::ParseTable schema[2];
+  static const ::google::protobuf::internal::FieldMetadata field_metadata[];
+  static const ::google::protobuf::internal::SerializationTable serialization_table[];
+  static const ::google::protobuf::uint32 offsets[];
+};
+void AddDescriptors();
+void InitDefaultsCommunication_parameterImpl();
+void InitDefaultsCommunication_parameter();
+void InitDefaultsCommunication_parameter_allImpl();
+void InitDefaultsCommunication_parameter_all();
+inline void InitDefaults() {
+  InitDefaultsCommunication_parameter();
+  InitDefaultsCommunication_parameter_all();
+}
+}  // namespace protobuf_communication_2eproto
+namespace Communication_proto {
+class Communication_parameter;
+class Communication_parameterDefaultTypeInternal;
+extern Communication_parameterDefaultTypeInternal _Communication_parameter_default_instance_;
+class Communication_parameter_all;
+class Communication_parameter_allDefaultTypeInternal;
+extern Communication_parameter_allDefaultTypeInternal _Communication_parameter_all_default_instance_;
+}  // namespace Communication_proto
+namespace Communication_proto {
+
+// ===================================================================
+
+class Communication_parameter : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:Communication_proto.Communication_parameter) */ {
+ public:
+  Communication_parameter();
+  virtual ~Communication_parameter();
+
+  Communication_parameter(const Communication_parameter& from);
+
+  inline Communication_parameter& operator=(const Communication_parameter& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  Communication_parameter(Communication_parameter&& from) noexcept
+    : Communication_parameter() {
+    *this = ::std::move(from);
+  }
+
+  inline Communication_parameter& operator=(Communication_parameter&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
+    return _internal_metadata_.unknown_fields();
+  }
+  inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
+    return _internal_metadata_.mutable_unknown_fields();
+  }
+
+  static const ::google::protobuf::Descriptor* descriptor();
+  static const Communication_parameter& default_instance();
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const Communication_parameter* internal_default_instance() {
+    return reinterpret_cast<const Communication_parameter*>(
+               &_Communication_parameter_default_instance_);
+  }
+  static PROTOBUF_CONSTEXPR int const kIndexInFileMessages =
+    0;
+
+  void Swap(Communication_parameter* other);
+  friend void swap(Communication_parameter& a, Communication_parameter& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline Communication_parameter* New() const PROTOBUF_FINAL { return New(NULL); }
+
+  Communication_parameter* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL;
+  void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL;
+  void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL;
+  void CopyFrom(const Communication_parameter& from);
+  void MergeFrom(const Communication_parameter& from);
+  void Clear() PROTOBUF_FINAL;
+  bool IsInitialized() const PROTOBUF_FINAL;
+
+  size_t ByteSizeLong() const PROTOBUF_FINAL;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) PROTOBUF_FINAL;
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const PROTOBUF_FINAL;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      bool deterministic, ::google::protobuf::uint8* target) const PROTOBUF_FINAL;
+  int GetCachedSize() const PROTOBUF_FINAL { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const PROTOBUF_FINAL;
+  void InternalSwap(Communication_parameter* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return NULL;
+  }
+  inline void* MaybeArenaPtr() const {
+    return NULL;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const PROTOBUF_FINAL;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // repeated string connect_string_vector = 2;
+  int connect_string_vector_size() const;
+  void clear_connect_string_vector();
+  static const int kConnectStringVectorFieldNumber = 2;
+  const ::std::string& connect_string_vector(int index) const;
+  ::std::string* mutable_connect_string_vector(int index);
+  void set_connect_string_vector(int index, const ::std::string& value);
+  #if LANG_CXX11
+  void set_connect_string_vector(int index, ::std::string&& value);
+  #endif
+  void set_connect_string_vector(int index, const char* value);
+  void set_connect_string_vector(int index, const char* value, size_t size);
+  ::std::string* add_connect_string_vector();
+  void add_connect_string_vector(const ::std::string& value);
+  #if LANG_CXX11
+  void add_connect_string_vector(::std::string&& value);
+  #endif
+  void add_connect_string_vector(const char* value);
+  void add_connect_string_vector(const char* value, size_t size);
+  const ::google::protobuf::RepeatedPtrField< ::std::string>& connect_string_vector() const;
+  ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_connect_string_vector();
+
+  // optional string bind_string = 1;
+  bool has_bind_string() const;
+  void clear_bind_string();
+  static const int kBindStringFieldNumber = 1;
+  const ::std::string& bind_string() const;
+  void set_bind_string(const ::std::string& value);
+  #if LANG_CXX11
+  void set_bind_string(::std::string&& value);
+  #endif
+  void set_bind_string(const char* value);
+  void set_bind_string(const char* value, size_t size);
+  ::std::string* mutable_bind_string();
+  ::std::string* release_bind_string();
+  void set_allocated_bind_string(::std::string* bind_string);
+
+  // @@protoc_insertion_point(class_scope:Communication_proto.Communication_parameter)
+ private:
+  void set_has_bind_string();
+  void clear_has_bind_string();
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::internal::HasBits<1> _has_bits_;
+  mutable int _cached_size_;
+  ::google::protobuf::RepeatedPtrField< ::std::string> connect_string_vector_;
+  ::google::protobuf::internal::ArenaStringPtr bind_string_;
+  friend struct ::protobuf_communication_2eproto::TableStruct;
+  friend void ::protobuf_communication_2eproto::InitDefaultsCommunication_parameterImpl();
+};
+// -------------------------------------------------------------------
+
+class Communication_parameter_all : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:Communication_proto.Communication_parameter_all) */ {
+ public:
+  Communication_parameter_all();
+  virtual ~Communication_parameter_all();
+
+  Communication_parameter_all(const Communication_parameter_all& from);
+
+  inline Communication_parameter_all& operator=(const Communication_parameter_all& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  Communication_parameter_all(Communication_parameter_all&& from) noexcept
+    : Communication_parameter_all() {
+    *this = ::std::move(from);
+  }
+
+  inline Communication_parameter_all& operator=(Communication_parameter_all&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
+    return _internal_metadata_.unknown_fields();
+  }
+  inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
+    return _internal_metadata_.mutable_unknown_fields();
+  }
+
+  static const ::google::protobuf::Descriptor* descriptor();
+  static const Communication_parameter_all& default_instance();
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const Communication_parameter_all* internal_default_instance() {
+    return reinterpret_cast<const Communication_parameter_all*>(
+               &_Communication_parameter_all_default_instance_);
+  }
+  static PROTOBUF_CONSTEXPR int const kIndexInFileMessages =
+    1;
+
+  void Swap(Communication_parameter_all* other);
+  friend void swap(Communication_parameter_all& a, Communication_parameter_all& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline Communication_parameter_all* New() const PROTOBUF_FINAL { return New(NULL); }
+
+  Communication_parameter_all* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL;
+  void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL;
+  void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL;
+  void CopyFrom(const Communication_parameter_all& from);
+  void MergeFrom(const Communication_parameter_all& from);
+  void Clear() PROTOBUF_FINAL;
+  bool IsInitialized() const PROTOBUF_FINAL;
+
+  size_t ByteSizeLong() const PROTOBUF_FINAL;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) PROTOBUF_FINAL;
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const PROTOBUF_FINAL;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      bool deterministic, ::google::protobuf::uint8* target) const PROTOBUF_FINAL;
+  int GetCachedSize() const PROTOBUF_FINAL { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const PROTOBUF_FINAL;
+  void InternalSwap(Communication_parameter_all* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return NULL;
+  }
+  inline void* MaybeArenaPtr() const {
+    return NULL;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const PROTOBUF_FINAL;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // optional .Communication_proto.Communication_parameter communication_parameters = 1;
+  bool has_communication_parameters() const;
+  void clear_communication_parameters();
+  static const int kCommunicationParametersFieldNumber = 1;
+  const ::Communication_proto::Communication_parameter& communication_parameters() const;
+  ::Communication_proto::Communication_parameter* release_communication_parameters();
+  ::Communication_proto::Communication_parameter* mutable_communication_parameters();
+  void set_allocated_communication_parameters(::Communication_proto::Communication_parameter* communication_parameters);
+
+  // @@protoc_insertion_point(class_scope:Communication_proto.Communication_parameter_all)
+ private:
+  void set_has_communication_parameters();
+  void clear_has_communication_parameters();
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::internal::HasBits<1> _has_bits_;
+  mutable int _cached_size_;
+  ::Communication_proto::Communication_parameter* communication_parameters_;
+  friend struct ::protobuf_communication_2eproto::TableStruct;
+  friend void ::protobuf_communication_2eproto::InitDefaultsCommunication_parameter_allImpl();
+};
+// ===================================================================
+
+
+// ===================================================================
+
+#ifdef __GNUC__
+  #pragma GCC diagnostic push
+  #pragma GCC diagnostic ignored "-Wstrict-aliasing"
+#endif  // __GNUC__
+// Communication_parameter
+
+// optional string bind_string = 1;
+inline bool Communication_parameter::has_bind_string() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void Communication_parameter::set_has_bind_string() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void Communication_parameter::clear_has_bind_string() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+inline void Communication_parameter::clear_bind_string() {
+  bind_string_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_bind_string();
+}
+inline const ::std::string& Communication_parameter::bind_string() const {
+  // @@protoc_insertion_point(field_get:Communication_proto.Communication_parameter.bind_string)
+  return bind_string_.GetNoArena();
+}
+inline void Communication_parameter::set_bind_string(const ::std::string& value) {
+  set_has_bind_string();
+  bind_string_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:Communication_proto.Communication_parameter.bind_string)
+}
+#if LANG_CXX11
+inline void Communication_parameter::set_bind_string(::std::string&& value) {
+  set_has_bind_string();
+  bind_string_.SetNoArena(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
+  // @@protoc_insertion_point(field_set_rvalue:Communication_proto.Communication_parameter.bind_string)
+}
+#endif
+inline void Communication_parameter::set_bind_string(const char* value) {
+  GOOGLE_DCHECK(value != NULL);
+  set_has_bind_string();
+  bind_string_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:Communication_proto.Communication_parameter.bind_string)
+}
+inline void Communication_parameter::set_bind_string(const char* value, size_t size) {
+  set_has_bind_string();
+  bind_string_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:Communication_proto.Communication_parameter.bind_string)
+}
+inline ::std::string* Communication_parameter::mutable_bind_string() {
+  set_has_bind_string();
+  // @@protoc_insertion_point(field_mutable:Communication_proto.Communication_parameter.bind_string)
+  return bind_string_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* Communication_parameter::release_bind_string() {
+  // @@protoc_insertion_point(field_release:Communication_proto.Communication_parameter.bind_string)
+  clear_has_bind_string();
+  return bind_string_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Communication_parameter::set_allocated_bind_string(::std::string* bind_string) {
+  if (bind_string != NULL) {
+    set_has_bind_string();
+  } else {
+    clear_has_bind_string();
+  }
+  bind_string_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), bind_string);
+  // @@protoc_insertion_point(field_set_allocated:Communication_proto.Communication_parameter.bind_string)
+}
+
+// repeated string connect_string_vector = 2;
+inline int Communication_parameter::connect_string_vector_size() const {
+  return connect_string_vector_.size();
+}
+inline void Communication_parameter::clear_connect_string_vector() {
+  connect_string_vector_.Clear();
+}
+inline const ::std::string& Communication_parameter::connect_string_vector(int index) const {
+  // @@protoc_insertion_point(field_get:Communication_proto.Communication_parameter.connect_string_vector)
+  return connect_string_vector_.Get(index);
+}
+inline ::std::string* Communication_parameter::mutable_connect_string_vector(int index) {
+  // @@protoc_insertion_point(field_mutable:Communication_proto.Communication_parameter.connect_string_vector)
+  return connect_string_vector_.Mutable(index);
+}
+inline void Communication_parameter::set_connect_string_vector(int index, const ::std::string& value) {
+  // @@protoc_insertion_point(field_set:Communication_proto.Communication_parameter.connect_string_vector)
+  connect_string_vector_.Mutable(index)->assign(value);
+}
+#if LANG_CXX11
+inline void Communication_parameter::set_connect_string_vector(int index, ::std::string&& value) {
+  // @@protoc_insertion_point(field_set:Communication_proto.Communication_parameter.connect_string_vector)
+  connect_string_vector_.Mutable(index)->assign(std::move(value));
+}
+#endif
+inline void Communication_parameter::set_connect_string_vector(int index, const char* value) {
+  GOOGLE_DCHECK(value != NULL);
+  connect_string_vector_.Mutable(index)->assign(value);
+  // @@protoc_insertion_point(field_set_char:Communication_proto.Communication_parameter.connect_string_vector)
+}
+inline void Communication_parameter::set_connect_string_vector(int index, const char* value, size_t size) {
+  connect_string_vector_.Mutable(index)->assign(
+    reinterpret_cast<const char*>(value), size);
+  // @@protoc_insertion_point(field_set_pointer:Communication_proto.Communication_parameter.connect_string_vector)
+}
+inline ::std::string* Communication_parameter::add_connect_string_vector() {
+  // @@protoc_insertion_point(field_add_mutable:Communication_proto.Communication_parameter.connect_string_vector)
+  return connect_string_vector_.Add();
+}
+inline void Communication_parameter::add_connect_string_vector(const ::std::string& value) {
+  connect_string_vector_.Add()->assign(value);
+  // @@protoc_insertion_point(field_add:Communication_proto.Communication_parameter.connect_string_vector)
+}
+#if LANG_CXX11
+inline void Communication_parameter::add_connect_string_vector(::std::string&& value) {
+  connect_string_vector_.Add(std::move(value));
+  // @@protoc_insertion_point(field_add:Communication_proto.Communication_parameter.connect_string_vector)
+}
+#endif
+inline void Communication_parameter::add_connect_string_vector(const char* value) {
+  GOOGLE_DCHECK(value != NULL);
+  connect_string_vector_.Add()->assign(value);
+  // @@protoc_insertion_point(field_add_char:Communication_proto.Communication_parameter.connect_string_vector)
+}
+inline void Communication_parameter::add_connect_string_vector(const char* value, size_t size) {
+  connect_string_vector_.Add()->assign(reinterpret_cast<const char*>(value), size);
+  // @@protoc_insertion_point(field_add_pointer:Communication_proto.Communication_parameter.connect_string_vector)
+}
+inline const ::google::protobuf::RepeatedPtrField< ::std::string>&
+Communication_parameter::connect_string_vector() const {
+  // @@protoc_insertion_point(field_list:Communication_proto.Communication_parameter.connect_string_vector)
+  return connect_string_vector_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::std::string>*
+Communication_parameter::mutable_connect_string_vector() {
+  // @@protoc_insertion_point(field_mutable_list:Communication_proto.Communication_parameter.connect_string_vector)
+  return &connect_string_vector_;
+}
+
+// -------------------------------------------------------------------
+
+// Communication_parameter_all
+
+// optional .Communication_proto.Communication_parameter communication_parameters = 1;
+inline bool Communication_parameter_all::has_communication_parameters() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void Communication_parameter_all::set_has_communication_parameters() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void Communication_parameter_all::clear_has_communication_parameters() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+inline void Communication_parameter_all::clear_communication_parameters() {
+  if (communication_parameters_ != NULL) communication_parameters_->Clear();
+  clear_has_communication_parameters();
+}
+inline const ::Communication_proto::Communication_parameter& Communication_parameter_all::communication_parameters() const {
+  const ::Communication_proto::Communication_parameter* p = communication_parameters_;
+  // @@protoc_insertion_point(field_get:Communication_proto.Communication_parameter_all.communication_parameters)
+  return p != NULL ? *p : *reinterpret_cast<const ::Communication_proto::Communication_parameter*>(
+      &::Communication_proto::_Communication_parameter_default_instance_);
+}
+inline ::Communication_proto::Communication_parameter* Communication_parameter_all::release_communication_parameters() {
+  // @@protoc_insertion_point(field_release:Communication_proto.Communication_parameter_all.communication_parameters)
+  clear_has_communication_parameters();
+  ::Communication_proto::Communication_parameter* temp = communication_parameters_;
+  communication_parameters_ = NULL;
+  return temp;
+}
+inline ::Communication_proto::Communication_parameter* Communication_parameter_all::mutable_communication_parameters() {
+  set_has_communication_parameters();
+  if (communication_parameters_ == NULL) {
+    communication_parameters_ = new ::Communication_proto::Communication_parameter;
+  }
+  // @@protoc_insertion_point(field_mutable:Communication_proto.Communication_parameter_all.communication_parameters)
+  return communication_parameters_;
+}
+inline void Communication_parameter_all::set_allocated_communication_parameters(::Communication_proto::Communication_parameter* communication_parameters) {
+  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
+  if (message_arena == NULL) {
+    delete communication_parameters_;
+  }
+  if (communication_parameters) {
+    ::google::protobuf::Arena* submessage_arena = NULL;
+    if (message_arena != submessage_arena) {
+      communication_parameters = ::google::protobuf::internal::GetOwnedMessage(
+          message_arena, communication_parameters, submessage_arena);
+    }
+    set_has_communication_parameters();
+  } else {
+    clear_has_communication_parameters();
+  }
+  communication_parameters_ = communication_parameters;
+  // @@protoc_insertion_point(field_set_allocated:Communication_proto.Communication_parameter_all.communication_parameters)
+}
+
+#ifdef __GNUC__
+  #pragma GCC diagnostic pop
+#endif  // __GNUC__
+// -------------------------------------------------------------------
+
+
+// @@protoc_insertion_point(namespace_scope)
+
+}  // namespace Communication_proto
+
+// @@protoc_insertion_point(global_scope)
+
+#endif  // PROTOBUF_communication_2eproto__INCLUDED

+ 14 - 0
plc调度节点/communication/communication.proto

@@ -0,0 +1,14 @@
+syntax = "proto2";
+package Communication_proto;
+
+message Communication_parameter
+{
+    optional string bind_string = 1;
+    repeated string connect_string_vector = 2;
+
+}
+
+message Communication_parameter_all
+{
+    optional Communication_parameter        communication_parameters=1;
+}

+ 93 - 0
plc调度节点/communication/communication_message.cpp

@@ -0,0 +1,93 @@
+//
+// Created by huli on 2020/6/29.
+//
+
+#include "communication_message.h"
+
+
+Communication_message::Communication_message()
+{
+	m_message_type = eBase_msg;
+	m_receive_time = std::chrono::system_clock::now();
+	m_timeout_ms = std::chrono::milliseconds(5000);		//超时默认5秒
+	m_sender = eEmpty;
+	m_receiver = eEmpty;
+//	m_message_buf = "";
+}
+
+Communication_message::Communication_message(std::string message_buf)
+{
+	m_message_type = eBase_msg;
+	m_receive_time = std::chrono::system_clock::now();
+	m_timeout_ms = std::chrono::milliseconds(5000);		//超时默认5秒
+	m_sender = eEmpty;
+	m_receiver = eEmpty;
+	m_message_buf = message_buf;
+}
+
+Communication_message::Communication_message(char* p_buf, int size)
+{
+	m_message_type = eBase_msg;
+	m_receive_time = std::chrono::system_clock::now();
+	m_timeout_ms = std::chrono::milliseconds(5000);		//超时默认5秒
+	m_sender = eEmpty;
+	m_receiver = eEmpty;
+	m_message_buf = std::string(p_buf, size);
+}
+
+
+
+Communication_message::~Communication_message()
+{
+
+}
+
+bool Communication_message::is_over_time()
+{
+	if ( std::chrono::system_clock::now() - m_receive_time > m_timeout_ms)
+	{
+	    return true;
+	}
+	else
+	{
+		return false;
+	}
+}
+
+
+void Communication_message::reset(const message::Base_info& base_info, std::string receive_string)
+{
+	m_message_type = (Message_type)(base_info.msg_type());
+
+	m_receive_time = std::chrono::system_clock::now();
+	m_timeout_ms = std::chrono::milliseconds(base_info.timeout_ms());
+	m_sender = (Communicator)(base_info.sender());
+	m_receiver = (Communicator)(base_info.receiver());
+	m_message_buf = receive_string;
+}
+
+Communication_message::Message_type Communication_message::get_message_type()
+{
+	return m_message_type;
+}
+Communication_message::Communicator Communication_message::get_sender()
+{
+	return m_sender;
+}
+Communication_message::Communicator Communication_message::get_receiver()
+{
+	return m_receiver;
+}
+std::string& Communication_message::get_message_buf()
+{
+	return m_message_buf;
+}
+
+std::chrono::system_clock::time_point Communication_message::get_receive_time()
+{
+	return m_receive_time;
+}
+
+
+
+

+ 148 - 0
plc调度节点/communication/communication_message.h

@@ -0,0 +1,148 @@
+//
+// Created by huli on 2020/6/29.
+//
+
+#ifndef NNXX_TESTS_COMMUNICATION_MESSAGE_H
+#define NNXX_TESTS_COMMUNICATION_MESSAGE_H
+
+#include "../error_code/error_code.h"
+
+#include <time.h>
+#include <sys/time.h>
+#include <chrono>
+//#include <iosfwd>
+
+#include <string>
+#include "../message/message_base.pb.h"
+
+
+class Communication_message
+{
+public:
+	//消息类型定义,每个在网络上传输的消息必须含有这个属性
+	enum Message_type
+	{
+		eBase_msg=0x00,
+		eCommand_msg=0x01,                      //指令消息
+
+
+		eLocate_status_msg=0x11,                //定位模块状态消息
+		eLocate_request_msg=0x12,               //定位请求消息
+		eLocate_response_msg=0x13,              //定位反馈消息
+
+		eLocate_sift_request_msg = 0x14,            //预测算法请求消息
+		eLocate_sift_response_msg = 0x15,           //预测算法反馈消息
+
+		eDispatch_status_msg=0x21,                	//调度模块硬件状态消息
+		eDispatch_request_msg=0x22,              	//请求调度消息
+		eDispatch_response_msg=0x23,             	//调度结果反馈消息
+
+		eParkspace_allocation_status_msg=0x31,  		//车位分配模块状态消息,包括车位信息
+		eParkspace_allocation_request_msg=0x32, 		//请求分配车位消息
+		eParkspace_allocation_response_msg=0x33,		//分配车位结果反馈消息
+		eParkspace_search_request_msg = 0x34,			//查询车位请求消息
+		eParkspace_search_response_msg = 0x35,			//查询车位反馈消息
+		eParkspace_release_request_msg = 0x36,			//释放车位请求消息
+		eParkspace_release_response_msg = 0x37,			//释放车位反馈消息
+		eParkspace_force_update_request_msg = 0x38,		//手动修改车位消息
+		eParkspace_force_update_response_msg = 0x39,	//手动修改车位反馈消息
+		eParkspace_confirm_alloc_request_msg = 0x3A,	//确认分配车位请求消息
+		eParkspace_confirm_alloc_response_msg = 0x3B,	//确认分配车位反馈消息
+        eParkspace_refresh_request_msg=0x3C,        	//请求更新车位数据
+        eParkspace_allocation_data_response_msg=0x3D,	//车位数据反馈消息
+		eParkspace_manual_search_request_msg = 0x3E,	//手动查询车位请求消息
+		eParkspace_manual_search_response_msg = 0x3F,	//手动查询车位反馈消息
+
+		eStore_command_request_msg=0x41,        	//终端停车请求消息
+		eStore_command_response_msg=0x42,       	//停车请求反馈消息
+		ePickup_command_request_msg=0x43,       	//取车请求消息
+		ePickup_command_response_msg=0x44,       	//取车请求反馈消息
+		eTerminal_status_msg = 0x50,	 			//终端状态消息
+
+
+		eStoring_process_statu_msg=0x90,        //停车指令进度条消息
+		ePicking_process_statu_msg=0x91,        //取车指令进度消息
+
+
+		eCentral_controller_statu_msg=0xa0,     //中控系统状态消息
+
+		eEntrance_manual_operation_msg=0xb0,            //针对出入口状态操作的手动消息
+		eProcess_manual_operation_msg=0xb1,             //针对流程的手动消息
+
+		eNotify_request_msg=0xc0,               //取车等候区通知请求
+		eNotify_response_msg=0xc1,              //等候区反馈
+		eNotify_status_msg=0xc2,                //等候区通知节点状态
+		eUnNormalized_module_statu_msg = 0xd0, //非标节点状态
+
+		eDispatch_plan_request_msg          = 0xe0,     //调度总规划的请求(用于启动整个调度算法)(调度管理->调度算法)
+		eDispatch_plan_response_msg         = 0xe1,     //调度总规划的答复(调度算法->调度管理)
+		eDispatch_control_request_msg       = 0xe2,     //调度控制的任务请求(调度算法->调度管理)
+		eDispatch_control_response_msg      = 0xe3,     //调度控制的任务答复(调度管理->调度算法)
+		eDispatch_manager_status_msg        = 0xea,     //调度管理的设备状态消息(调度底下所有硬件设备状态的汇总)
+		eDispatch_manager_data_msg          = 0xeb,     //调度管理的设备详细的数据信息
+		
+		
+		eGround_detect_request_msg=0xf0,        //地面雷达测量请求消息
+    	eGround_detect_response_msg=0xf1,       //地面雷达测量反馈消息
+		eGround_status_msg=0xf2,                //地面雷达状态消息
+
+
+	};
+
+//通讯单元
+	enum Communicator
+	{
+		eEmpty=0x0000,
+		eMain=0x0001,    //主流程
+
+		eTerminor=0x0100,
+		//车位表
+		eParkspace=0x0200,
+		//测量单元
+		eMeasurer=0x0300,
+		//测量单元
+		eMeasurer_sift_server=0x0301,
+
+		//调度机构
+		eDispatch_mamager=0x0400,
+		//调度机构
+		eDispatch_control=0x0401,
+		//取车等候区通知节点
+		eNotify=0x0501,
+
+		//地面测量单元
+		eGround_measurer=0x0f00,
+	};
+public:
+	Communication_message();
+	Communication_message(std::string message_buf);
+	Communication_message(char* p_buf, int size);
+	Communication_message(const Communication_message& other)= default;
+	Communication_message& operator =(const Communication_message& other)= default;
+	~Communication_message();
+public://API functions
+	bool is_over_time();
+public://get or set member variable
+	void reset(const message::Base_info& base_info, std::string receive_string);
+
+	Message_type get_message_type();
+	Communicator get_sender();
+	Communicator get_receiver();
+	std::string& get_message_buf();
+	std::chrono::system_clock::time_point get_receive_time();
+
+protected://member variable
+	Message_type								m_message_type;				//消息类型
+	std::chrono::system_clock::time_point		m_receive_time;				//接收消息的时间点
+	std::chrono::milliseconds					m_timeout_ms;				//超时时间, 整个软件都统一为毫秒
+	Communicator								m_sender;					//发送者
+	Communicator								m_receiver;					//接受者
+
+	std::string									m_message_buf;				//消息数据
+
+private:
+
+};
+
+
+#endif //NNXX_TESTS_COMMUNICATION_MESSAGE_H

+ 608 - 0
plc调度节点/communication/communication_socket_base.cpp

@@ -0,0 +1,608 @@
+
+
+
+#include "communication_socket_base.h"
+#include "../tool/proto_tool.h"
+
+Communication_socket_base::Communication_socket_base()
+{
+	m_communication_statu = COMMUNICATION_UNKNOW;
+
+	mp_receive_data_thread = NULL;
+	mp_analysis_data_thread = NULL;
+	mp_send_data_thread = NULL;
+	mp_encapsulate_data_thread = NULL;
+
+	m_analysis_cycle_time = 1000;//默认1000ms,就自动解析(接受list)
+	m_encapsulate_cycle_time = 1000;//默认1000ms,就自动发送一次状态信息
+}
+
+Communication_socket_base::~Communication_socket_base()
+{
+	communication_uninit();
+}
+
+//初始化 通信 模块。如下三选一
+Error_manager Communication_socket_base::communication_init()
+{
+	LOG(INFO) << " ---Communication_socket_base::communication_init() run--- "<< this;
+
+	return  communication_init_from_protobuf(COMMUNICATION_PARAMETER_PATH);
+}
+
+//初始化 通信 模块。从文件读取
+Error_manager Communication_socket_base::communication_init_from_protobuf(std::string prototxt_path)
+{
+	Communication_proto::Communication_parameter_all t_communication_parameter_all;
+	if(!  proto_tool::read_proto_param(prototxt_path,t_communication_parameter_all) )
+	{
+		return Error_manager(COMMUNICATION_READ_PROTOBUF_ERROR,MINOR_ERROR,
+		"Communication_socket_base read_proto_param  failed");
+	}
+	return communication_init_from_protobuf(t_communication_parameter_all);
+}
+
+//初始化 通信 模块。从protobuf读取
+Error_manager Communication_socket_base::communication_init_from_protobuf(Communication_proto::Communication_parameter_all& communication_parameter_all)
+{
+	LOG(INFO) << " ---Communication_socket_base::communication_init_from_protobuf() run--- "<< this;
+	Error_manager t_error;
+
+	if ( communication_parameter_all.communication_parameters().has_bind_string() )
+	{
+		t_error = communication_bind(communication_parameter_all.communication_parameters().bind_string());
+		if ( t_error != Error_code::SUCCESS )
+		{
+			return t_error;
+		}
+	}
+//	std::cout << "communication_parameter_all.communication_parameters().connect_string_vector_size() " <<
+//		communication_parameter_all.communication_parameters().connect_string_vector_size()<< std::endl;
+	for(int i=0;i<communication_parameter_all.communication_parameters().connect_string_vector_size();++i)
+	{
+		t_error = communication_connect( communication_parameter_all.communication_parameters().connect_string_vector(i) );
+		if ( t_error != Error_code::SUCCESS )
+		{
+			return t_error;
+		}
+	}
+	//启动通信, run thread
+	communication_run();
+
+	return Error_code::SUCCESS;
+}
+
+//初始化
+Error_manager Communication_socket_base::communication_init(std::string bind_string, std::vector<std::string>& connect_string_vector)
+{
+	LOG(INFO) << " ---Communication_socket_base::communication_init() run--- "<< this;
+	Error_manager t_error;
+
+	t_error = communication_bind(bind_string);
+	if ( t_error != Error_code::SUCCESS )
+	{
+		return t_error;
+	}
+
+	t_error = communication_connect(connect_string_vector);
+	if ( t_error != Error_code::SUCCESS )
+	{
+		return t_error;
+	}
+
+	//启动通信, run thread
+	communication_run();
+
+	return Error_code::SUCCESS;
+}
+//bind
+Error_manager Communication_socket_base::communication_bind(std::string bind_string)
+{
+	Error_manager t_error;
+	int t_socket_result;
+
+	//m_socket 自己作为一个服务器, 绑定一个端口
+	t_socket_result = m_socket.bind(bind_string);
+	if ( t_socket_result <0 )
+	{
+		return Error_manager(Error_code::COMMUNICATION_BIND_ERROR, Error_level::MINOR_ERROR,
+							 " m_socket.bind error ");
+	}
+	LOG(INFO) << " ---Communication_socket_base::communication_bind() bind::  "<< bind_string << "  " << this;
+
+	return Error_code::SUCCESS;
+}
+//connect
+Error_manager Communication_socket_base::communication_connect(std::vector<std::string>& connect_string_vector)
+{
+	Error_manager t_error;
+	for (auto iter = connect_string_vector.begin(); iter != connect_string_vector.end(); ++iter)
+	{
+		t_error = communication_connect(*iter);
+		if ( t_error != Error_code::SUCCESS )
+		{
+			return t_error;
+		}
+	}
+	return Error_code::SUCCESS;
+}
+//connect
+Error_manager Communication_socket_base::communication_connect(std::string connect_string)
+{
+	Error_manager t_error;
+	int t_socket_result;
+	//m_socket 和远端通信, 连接远端服务器的端口
+	t_socket_result = m_socket.connect(connect_string);
+	if ( t_socket_result <0 )
+	{
+		return Error_manager(Error_code::COMMUNICATION_CONNECT_ERROR, Error_level::MINOR_ERROR,
+							 " m_socket.connect error ");
+	}
+	LOG(INFO) << " ---Communication_socket_base::communication_connect() connect::  "<< connect_string << "  " << this;
+
+	return Error_code::SUCCESS;
+}
+//启动通信, run thread
+Error_manager Communication_socket_base::communication_run()
+{
+	m_communication_statu = COMMUNICATION_READY;
+	//启动4个线程。
+	//接受线程默认循环, 内部的nn_recv进行等待, 超时1ms
+	m_receive_condition.reset(false, false, false);
+	mp_receive_data_thread = new std::thread(&Communication_socket_base::receive_data_thread, this);
+	//解析线程默认等待, 需要接受线程去唤醒, 超时1ms, 超时后主动遍历m_receive_data_list
+	m_analysis_data_condition.reset(false, false, false);
+	mp_analysis_data_thread = new std::thread(&Communication_socket_base::analysis_data_thread, this);
+	//发送线程默认循环, 内部的wait_and_pop进行等待,
+	m_send_data_condition.reset(false, true, false);
+	mp_send_data_thread = new std::thread(&Communication_socket_base::send_data_thread, this);
+	//封装线程默认等待, ...., 超时1ms, 超时后主动 封装心跳和状态信息,
+	m_encapsulate_data_condition.reset(false, false, false);
+	mp_encapsulate_data_thread = new std::thread(&Communication_socket_base::encapsulate_data_thread, this);
+
+	return Error_code::SUCCESS;
+}
+
+
+//反初始化 通信 模块。
+Error_manager Communication_socket_base::communication_uninit()
+{
+	//终止list,防止 wait_and_pop 阻塞线程。
+	m_receive_data_list.termination_list();
+	m_send_data_list.termination_list();
+
+	//杀死4个线程,强制退出
+	if (mp_receive_data_thread)
+	{
+		m_receive_condition.kill_all();
+	}
+	if (mp_analysis_data_thread)
+	{
+		m_analysis_data_condition.kill_all();
+	}
+	if (mp_send_data_thread)
+	{
+		m_send_data_condition.kill_all();
+	}
+	if (mp_encapsulate_data_thread)
+	{
+		m_encapsulate_data_condition.kill_all();
+	}
+	//回收4个线程的资源
+	if (mp_receive_data_thread)
+	{
+		mp_receive_data_thread->join();
+		delete mp_receive_data_thread;
+		mp_receive_data_thread = NULL;
+	}
+	if (mp_analysis_data_thread)
+	{
+		mp_analysis_data_thread->join();
+		delete mp_analysis_data_thread;
+		mp_analysis_data_thread = 0;
+	}
+	if (mp_send_data_thread)
+	{
+		mp_send_data_thread->join();
+		delete mp_send_data_thread;
+		mp_send_data_thread = NULL;
+	}
+	if (mp_encapsulate_data_thread)
+	{
+		mp_encapsulate_data_thread->join();
+		delete mp_encapsulate_data_thread;
+		mp_encapsulate_data_thread = NULL;
+	}
+
+	//清空list
+	m_receive_data_list.clear_and_delete();
+	m_send_data_list.clear_and_delete();
+
+	m_communication_statu = COMMUNICATION_UNKNOW;
+	m_socket.close();
+
+	return Error_code::SUCCESS;
+}
+
+
+void Communication_socket_base::set_analysis_cycle_time(unsigned int analysis_cycle_time)
+{
+	m_analysis_cycle_time = analysis_cycle_time;
+}
+void Communication_socket_base::set_encapsulate_cycle_time(unsigned int encapsulate_cycle_time)
+{
+	m_encapsulate_cycle_time = encapsulate_cycle_time;
+}
+
+
+
+
+//mp_receive_data_thread 接受线程执行函数,
+//receive_data_thread 内部线程负责接受消息
+void Communication_socket_base::receive_data_thread()
+{
+	LOG(INFO) << " Communication_socket_base::receive_data_thread start "<< this;
+
+	//通信接受线程, 负责接受socket消息, 并存入 m_receive_data_list
+	while (m_receive_condition.is_alive())
+	{
+		m_receive_condition.wait_for_ex(std::chrono::microseconds(1));
+		if ( m_receive_condition.is_alive() )
+		{
+			std::this_thread::yield();
+
+			std::string t_receive_string;
+			{//这个大括号表示只对 recv 和 send 加锁, 不要因为后面的复杂逻辑影响通信效率
+				std::unique_lock<std::mutex> lk(m_mutex);
+				//flags为1, 非阻塞接受消息, 如果接收到消息, 那么接受数据长度大于0
+				t_receive_string = m_socket.recv<std::string>(1);
+			}
+			if ( t_receive_string.size()>0 )
+			{
+				//如果这里接受到了消息, 在这提前解析消息最前面的Base_msg (消息公共内容), 用于后续的check
+				message::Base_msg t_base_msg;
+				if( t_base_msg.ParseFromString(t_receive_string) )
+				{
+					//第一次解析之后转化为, Communication_message, 自定义的通信消息格式
+					Communication_message  * tp_communication_message = new Communication_message;
+					tp_communication_message->reset(t_base_msg.base_info(), t_receive_string);
+					//检查消息是否有效, 主要检查消息类型和接受者, 判断这条消息是不是给我的.
+					if ( check_msg(tp_communication_message) == SUCCESS )
+					{
+						bool is_push = m_receive_data_list.push(tp_communication_message);
+						//push成功之后, tp_communication_message内存的管理权限交给链表, 如果失败就要回收内存
+						if ( is_push )
+						{
+							//唤醒解析线程一次,
+							m_analysis_data_condition.notify_all(false, true);
+						}
+						else
+						{
+//						push失败, 就要回收内存
+							delete(tp_communication_message);
+							tp_communication_message = NULL;
+//					return Error_manager(Error_code::CONTAINER_IS_TERMINATE, Error_level::MINOR_ERROR,
+//										 " m_receive_data_list.push error ");
+						}
+					}
+					else
+					{
+						delete(tp_communication_message);
+						tp_communication_message = NULL;
+					}
+
+
+				}
+				//解析失败, 就当做什么也没发生, 认为接收消息无效,
+			}
+			//没有接受到消息, 返回空字符串
+		}
+	}
+
+	LOG(INFO) << " Communication_socket_base::receive_data_thread end "<< this;
+	return;
+}
+
+//检查消息是否有效, 主要检查消息类型和接受者, 判断这条消息是不是给我的.
+Error_manager Communication_socket_base::check_msg(Communication_message*  p_msg)
+{
+	//通过 p_msg->get_message_type() 和 p_msg->get_receiver() 判断这条消息是不是给我的.
+	//子类重载时, 增加自己模块的判断逻辑, 以后再写.
+	if ( p_msg->get_message_type() == Communication_message::Message_type::eBase_msg
+		 && p_msg->get_receiver() == Communication_message::Communicator::eMain )
+	{
+		return Error_code::SUCCESS;
+	}
+	else
+	{
+		//无效的消息,
+		return Error_manager(Error_code::INVALID_MESSAGE, Error_level::NEGLIGIBLE_ERROR,
+							 " INVALID_MESSAGE error ");	}
+}
+
+//mp_analysis_data_thread 解析线程执行函数,
+//analysis_data_thread 内部线程负责解析消息
+void Communication_socket_base::analysis_data_thread()
+{
+	LOG(INFO) << " Communication_socket_base::analysis_data_thread start "<< this;
+
+	//通信解析线程, 负责巡检m_receive_data_list, 并解析和处理消息
+	while (m_analysis_data_condition.is_alive())
+	{
+		bool t_pass_flag = m_analysis_data_condition.wait_for_millisecond(m_analysis_cycle_time);
+		if ( m_analysis_data_condition.is_alive() )
+		{
+			std::this_thread::yield();
+			//如果解析线程被主动唤醒, 那么就表示 收到新的消息, 那就遍历整个链表
+			if ( t_pass_flag )
+			{
+				analysis_receive_list();
+			}
+				//如果解析线程超时通过, 那么就定时处理链表残留的消息,
+			else
+			{
+				analysis_receive_list();
+			}
+		}
+	}
+
+	LOG(INFO) << " Communication_socket_base::analysis_data_thread end "<< this;
+	return;
+}
+
+//循环接受链表, 解析消息,
+Error_manager Communication_socket_base::analysis_receive_list()
+{
+	Error_manager t_error;
+	if ( m_receive_data_list.m_termination_flag )
+	{
+		return Error_manager(Error_code::CONTAINER_IS_TERMINATE, Error_level::MINOR_ERROR,
+							 " Communication_socket_base::analysis_receive_list error ");
+	}
+	else
+	{
+		std::unique_lock<std::mutex> lk(m_receive_data_list.m_mutex);
+		for (auto iter = m_receive_data_list.m_data_list.begin(); iter != m_receive_data_list.m_data_list.end(); )
+		{
+			Communication_message* tp_msg = **iter;
+			if ( tp_msg == NULL )
+			{
+				iter = m_receive_data_list.m_data_list.erase(iter);
+				//注:erase 删除当前 iter 之后返回下一个节点,当前的 iter 无效化,
+			}
+			else
+			{
+				//检查消息是否可以被处理
+				t_error = check_executer(tp_msg);
+				if ( t_error == SUCCESS)
+				{
+					//处理消息
+					t_error = execute_msg(tp_msg);
+//				if ( t_error )
+//				{
+//					//执行结果不管
+//				}
+//				else
+//				{
+//					//执行结果不管
+//				}
+					delete(tp_msg);
+					tp_msg = NULL;
+					iter = m_receive_data_list.m_data_list.erase(iter);
+					//注:erase 删除当前 iter 之后返回下一个节点,当前的 iter 无效化,
+				}
+				else if( t_error == COMMUNICATION_EXCUTER_IS_BUSY)
+				{
+					//处理器正忙, 那就不做处理, 直接处理下一个
+					//注:这条消息就被保留了下来, wait_for_millisecond 超时通过之后, 会循环检查残留的消息.
+					iter++;
+				}
+				else //if( t_error == COMMUNICATION_ANALYSIS_TIME_OUT )
+				{
+					//超时了就直接删除
+					delete(tp_msg);
+					tp_msg = NULL;
+					iter = m_receive_data_list.m_data_list.erase(iter);
+					//注:erase 删除当前 iter 之后返回下一个节点,当前的 iter 无效化,
+
+					//注:消息删除之后, 不需要发送答复消息, 发送方也会有超时处理的,  只有 execute_msg 里面可以答复消息
+				}
+			}
+		}
+	}
+	return Error_code::SUCCESS;
+}
+
+
+
+//检查执行者的状态, 判断能否处理这条消息, 需要子类重载
+Error_manager Communication_socket_base::check_executer(Communication_message*  p_msg)
+{
+	//检查对应模块的状态, 判断是否可以处理这条消息
+	//同时也要判断是否超时, 超时返回 COMMUNICATION_ANALYSIS_TIME_OUT
+	//如果处理器正在忙别的, 那么返回 COMMUNICATION_EXCUTER_IS_BUSY
+
+	if ( p_msg->is_over_time() )
+	{
+		std::cout << "Communication_socket_base::check_msg  p_buf =  " << p_msg->get_message_buf() << std::endl;
+		std::cout << "Communication_socket_base::check_msg   size =  " << p_msg->get_message_buf().size() << std::endl;
+		std::cout << "COMMUNICATION_ANALYSIS_TIME_OUT , " << std::endl;
+		return Error_code::COMMUNICATION_ANALYSIS_TIME_OUT;
+	}
+	else
+	{
+		bool executer_is_ready = false;
+		//通过 p_msg->get_message_type() 和 p_msg->get_receiver() 找到处理模块的实例对象, 查询执行人是否可以处理这条消息
+		//这里子类重载时, 增加判断逻辑, 以后再写.
+		executer_is_ready = true;
+
+		std::cout << "Communication_socket_base::check_msg  p_buf =  " << p_msg->get_message_buf() << std::endl;
+		std::cout << "Communication_socket_base::check_msg   size =  " << p_msg->get_message_buf().size() << std::endl;
+
+		if ( executer_is_ready )
+		{
+			std::cout << "executer_is_ready , " << std::endl;
+			return Error_code::SUCCESS;
+		}
+		else
+		{
+			std::cout << "executer_is_busy , " << std::endl;
+			return Error_code::COMMUNICATION_EXCUTER_IS_BUSY;
+		}
+	}
+
+	return Error_code::SUCCESS;
+}
+
+//处理消息
+Error_manager Communication_socket_base::execute_msg(Communication_message*  p_msg)
+{
+	//先将 p_msg 转化为 对应的格式, 使用对应模块的protobuf来二次解析
+	// 不能一直使用 Communication_message*  p_msg, 这个是要销毁的
+	//然后处理这个消息, 就是调用对应模块的 execute 接口函数
+	//执行结果不管, 如果需要答复, 那么对应模块 在自己内部 封装一条消息发送即可.
+	//子类重载, 需要完全重写, 以后再写.
+
+	//注注注注注意了, 本模块只是用来做通信,
+	//在做处理消息的时候, 可能会调用执行者的接口函数,
+	//这里不应该长时间阻塞或者处理复杂的逻辑,
+	//请执行者另开线程来处理任务.
+
+	std::cout << "Communication_socket_base::excute_msg  p_buf =  " << p_msg->get_message_buf() << std::endl;
+	std::cout << "Communication_socket_base::excute_msg   size =  " << p_msg->get_message_buf().size() << std::endl;
+	return Error_code::SUCCESS;
+}
+
+//mp_send_data_thread 发送线程执行函数,
+//send_data_thread 内部线程负责发送消息
+void Communication_socket_base::send_data_thread()
+{
+	LOG(INFO) << " Communication_socket_base::send_data_thread start "<< this;
+
+	//通信发送线程, 负责巡检m_send_data_list, 并发送消息
+	while (m_send_data_condition.is_alive())
+	{
+		m_send_data_condition.wait();
+		if ( m_send_data_condition.is_alive() )
+		{
+			std::this_thread::yield();
+
+			Communication_message* tp_msg = NULL;
+			//这里 wait_and_pop 会使用链表内部的 m_data_cond 条件变量来控制等待,
+			//封装线程使用push的时候, 会唤醒线程并通过等待, 此时 m_send_data_condition 是一直通过的.
+			//如果需要退出, 那么就要 m_send_data_list.termination_list();	和 m_send_data_condition.kill_all();
+			bool is_pop = m_send_data_list.wait_and_pop(tp_msg);
+			if ( is_pop )
+			{
+				if ( tp_msg != NULL )
+				{
+					{//这个大括号表示只对 recv 和 send 加锁, 不要因为后面的复杂逻辑影响通信效率
+						std::unique_lock<std::mutex> lk(m_mutex);
+						m_socket.send(tp_msg->get_message_buf());
+					}
+					delete(tp_msg);
+					tp_msg = NULL;
+				}
+			}
+			else
+			{
+				//没有取出, 那么应该就是 m_termination_flag 结束了
+//				return Error_manager(Error_code::CONTAINER_IS_TERMINATE, Error_level::MINOR_ERROR,
+//									 " Communication_socket_base::send_data_thread() error ");
+			}
+		}
+	}
+
+	LOG(INFO) << " Communication_socket_base::send_data_thread end "<< this;
+	return;
+}
+
+//mp_encapsulate_data_thread 封装线程执行函数,
+//encapsulate_data_thread 内部线程负责封装消息
+void Communication_socket_base::encapsulate_data_thread()
+{
+	LOG(INFO) << " Communication_socket_base::encapsulate_data_thread start "<< this;
+
+	//通信封装线程, 负责定时封装消息, 并存入 m_send_data_list
+	while (m_encapsulate_data_condition.is_alive())
+	{
+		bool t_pass_flag = m_encapsulate_data_condition.wait_for_millisecond(m_encapsulate_cycle_time);
+
+		if ( m_encapsulate_data_condition.is_alive() )
+		{
+			std::this_thread::yield();
+			//如果封装线程被主动唤醒, 那么就表示 需要主动发送消息,
+			if ( t_pass_flag )
+			{
+				//主动发送消息,
+			}
+				//如果封装线程超时通过, 那么就定时封装心跳和状态信息
+			else
+			{
+				encapsulate_send_data();
+			}
+		}
+	}
+
+	LOG(INFO) << " Communication_socket_base::encapsulate_data_thread end "<< this;
+	return;
+}
+
+
+//定时封装发送消息, 一般为心跳和状态信息, 需要子类重载
+Error_manager Communication_socket_base::encapsulate_send_data()
+{
+//	char buf[256] = {0};
+//	static unsigned int t_heartbeat = 0;
+//	sprintf(buf, "Communication_socket_base, heartbeat = %d\0\0\0, test\0", t_heartbeat);
+//	t_heartbeat++;
+    return SUCCESS;
+	message::Base_msg t_base_msg;
+	t_base_msg.mutable_base_info()->set_msg_type(message::Message_type::eBase_msg);
+	t_base_msg.mutable_base_info()->set_timeout_ms(5000);
+	t_base_msg.mutable_base_info()->set_sender(message::Communicator::eMain);
+	t_base_msg.mutable_base_info()->set_receiver(message::Communicator::eMain);
+
+	Communication_message* tp_msg = new Communication_message(t_base_msg.SerializeAsString());
+	bool is_push = m_send_data_list.push(tp_msg);
+	if ( is_push == false )
+	{
+		delete(tp_msg);
+		tp_msg = NULL;
+		return Error_manager(Error_code::CONTAINER_IS_TERMINATE, Error_level::MINOR_ERROR,
+							 " Communication_socket_base::encapsulate_msg error ");
+	}
+	return Error_code::SUCCESS;
+}
+
+
+
+//封装消息, 需要子类重载
+Error_manager Communication_socket_base::encapsulate_msg(std::string message)
+{
+	Communication_message* tp_msg = new Communication_message(message);
+	bool is_push = m_send_data_list.push(tp_msg);
+	if ( is_push == false )
+	{
+		delete(tp_msg);
+		tp_msg = NULL;
+		return Error_manager(Error_code::CONTAINER_IS_TERMINATE, Error_level::MINOR_ERROR,
+							 " Communication_socket_base::encapsulate_msg error ");
+	}
+	return Error_code::SUCCESS;
+}
+
+//封装消息, 需要子类重载
+Error_manager Communication_socket_base::encapsulate_msg(Communication_message* p_msg)
+{
+	Communication_message* tp_msg = new Communication_message(*p_msg);
+	bool is_push = m_send_data_list.push(tp_msg);
+	if ( is_push == false )
+	{
+		delete(tp_msg);
+		tp_msg = NULL;
+		return Error_manager(Error_code::CONTAINER_IS_TERMINATE, Error_level::MINOR_ERROR,
+							 " Communication_socket_base::encapsulate_msg error ");
+	}
+	return Error_code::SUCCESS;
+}

+ 169 - 0
plc调度节点/communication/communication_socket_base.h

@@ -0,0 +1,169 @@
+
+
+/*
+ * communication_socket_base 通信模块的基类,
+ * 用户从这个基类继承, 初始化之后, 便可以自动进行通信
+ * 重载解析消息和封装消息,
+ *
+ *Thread_safe_list<Binary_buf*> 使用 Binary_buf , 而不是string
+ * 主要是为了支持直接发送数字0
+ * 
+ * 
+ * */
+
+#ifndef __COMMUNICATION_SOCKET_BASE__HH__
+#define __COMMUNICATION_SOCKET_BASE__HH__
+
+#include <mutex>
+#include <thread>
+#include <nnxx/message>
+#include <nnxx/socket.h>
+#include <nnxx/bus.h>
+
+#include <glog/logging.h>
+#include "../error_code/error_code.h"
+#include "../tool/binary_buf.h"
+#include "../tool/thread_safe_list.h"
+#include "../tool/thread_condition.h"
+
+#include "../communication/communication.pb.h"
+#include "../communication/communication_message.h"
+
+#include "../message/message_base.pb.h"
+//#include "../message/measure_message.pb.h"
+
+
+
+#define COMMUNICATION_PARAMETER_PATH "../setting/communication.prototxt"
+#define COMMUNICATION_PARAMETER_PATH_A "../setting/communication_a.prototxt"
+#define COMMUNICATION_PARAMETER_PATH_B "../setting/communication_b.prototxt"
+#define COMMUNICATION_PARAMETER_PATH_C "../setting/communication_c.prototxt"
+
+class Communication_socket_base
+{
+	//通信状态
+	enum Communication_statu
+	{
+		COMMUNICATION_UNKNOW		=0,	        //通信状态 未知
+		COMMUNICATION_READY			=1,			//通信状态 正常
+
+		COMMUNICATION_FAULT			=3,         //通信状态 错误
+	};
+
+public:
+	Communication_socket_base();
+	Communication_socket_base(const Communication_socket_base& other)= delete;
+	Communication_socket_base& operator =(const Communication_socket_base& other)= delete;
+	~Communication_socket_base();
+public://API functions
+	//初始化 通信 模块。如下三选一
+	virtual Error_manager communication_init();
+	//初始化 通信 模块。从文件读取
+	Error_manager communication_init_from_protobuf(std::string prototxt_path);
+	//初始化 通信 模块。从protobuf读取
+	Error_manager communication_init_from_protobuf(Communication_proto::Communication_parameter_all& communication_parameter_all);
+
+	//初始化
+	virtual Error_manager communication_init(std::string bind_string, std::vector<std::string>& connect_string_vector);
+	//bind
+	virtual Error_manager communication_bind(std::string bind_string);
+	//connect
+	virtual Error_manager communication_connect(std::vector<std::string>& connect_string_vector);
+	//connect
+	virtual Error_manager communication_connect(std::string connect_string);
+	//启动通信, run thread
+	virtual Error_manager communication_run();
+
+	//反初始化 通信 模块。
+	virtual Error_manager communication_uninit();
+	
+	
+public://get or set member variable
+	void set_analysis_cycle_time(unsigned int analysis_cycle_time);
+	void set_encapsulate_cycle_time(unsigned int encapsulate_cycle_time);
+
+protected:
+	//mp_receive_data_thread 接受线程执行函数,
+	//receive_data_thread 内部线程负责接受消息
+	void receive_data_thread();
+
+	//检查消息是否有效, 主要检查消息类型和接受者, 判断这条消息是不是给我的.
+	virtual Error_manager check_msg(Communication_message* p_msg);
+
+	//mp_analysis_data_thread 解析线程执行函数,
+	//analysis_data_thread 内部线程负责解析消息
+	void analysis_data_thread();
+
+	//遍历接受链表, 解析消息,
+	Error_manager analysis_receive_list();
+
+	//检查执行者的状态, 判断能否处理这条消息, 需要子类重载
+	virtual Error_manager check_executer(Communication_message* p_msg);
+
+	//处理消息, 需要子类重载
+	virtual Error_manager execute_msg(Communication_message* p_msg);
+
+	//mp_send_data_thread 发送线程执行函数,
+	//send_data_thread 内部线程负责发送消息
+	void send_data_thread();
+
+	//mp_encapsulate_data_thread 封装线程执行函数,
+	//encapsulate_data_thread 内部线程负责封装消息
+	void encapsulate_data_thread();
+
+	//定时封装发送消息, 一般为心跳和状态信息, 需要子类重载
+	virtual Error_manager encapsulate_send_data();
+
+public:
+	//封装消息, 需要子类重载
+	virtual Error_manager encapsulate_msg(std::string message);
+	//封装消息, 需要子类重载
+	virtual Error_manager encapsulate_msg(Communication_message* p_msg);
+
+protected://member variable
+
+	//通用的网络编程接口, 默认使用总线模式, (网状结构)
+	nnxx::socket 						m_socket { nnxx::SP, nnxx::BUS };
+	std::mutex 							m_mutex;				//m_socket的锁
+
+	//通信状态
+	Communication_statu 				m_communication_statu;			//通信状态
+
+	//接受模块,
+	Thread_safe_list<Communication_message*>		m_receive_data_list; 			//接受的list容器
+	std::thread*						mp_receive_data_thread;    		//接受的线程指针
+	Thread_condition					m_receive_condition;			//接受的条件变量
+	std::thread*						mp_analysis_data_thread;    	//解析的线程指针
+	Thread_condition					m_analysis_data_condition;		//解析的条件变量
+	unsigned int 						m_analysis_cycle_time;			//自动解析的时间周期
+
+	//发送模块,
+	Thread_safe_list<Communication_message*>		m_send_data_list;				//发送的list容器
+	std::thread*						mp_send_data_thread;    		//发送的线程指针
+	Thread_condition					m_send_data_condition;			//发送的条件变量
+	std::thread*						mp_encapsulate_data_thread;    	//封装的线程指针
+	Thread_condition					m_encapsulate_data_condition;	//封装的条件变量
+	unsigned int 						m_encapsulate_cycle_time;		//自动封装的时间周期
+
+
+
+private:
+
+};
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#endif //__COMMUNICATION_SOCKET_BASE__HH__

+ 994 - 0
plc调度节点/dispatch/database_communication_configuration.pb.cc

@@ -0,0 +1,994 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: database_communication_configuration.proto
+
+#include "database_communication_configuration.pb.h"
+
+#include <algorithm>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/port.h>
+#include <google/protobuf/stubs/once.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/wire_format_lite_inl.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/generated_message_reflection.h>
+#include <google/protobuf/reflection_ops.h>
+#include <google/protobuf/wire_format.h>
+// This is a temporary google only hack
+#ifdef GOOGLE_PROTOBUF_ENFORCE_UNIQUENESS
+#include "third_party/protobuf/version.h"
+#endif
+// @@protoc_insertion_point(includes)
+namespace parkspace_proto {
+class Database_communication_configurationDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<Database_communication_configuration>
+      _instance;
+} _Database_communication_configuration_default_instance_;
+class Database_communication_configuration_allDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<Database_communication_configuration_all>
+      _instance;
+} _Database_communication_configuration_all_default_instance_;
+}  // namespace parkspace_proto
+namespace protobuf_database_5fcommunication_5fconfiguration_2eproto {
+void InitDefaultsDatabase_communication_configurationImpl() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+#ifdef GOOGLE_PROTOBUF_ENFORCE_UNIQUENESS
+  ::google::protobuf::internal::InitProtobufDefaultsForceUnique();
+#else
+  ::google::protobuf::internal::InitProtobufDefaults();
+#endif  // GOOGLE_PROTOBUF_ENFORCE_UNIQUENESS
+  {
+    void* ptr = &::parkspace_proto::_Database_communication_configuration_default_instance_;
+    new (ptr) ::parkspace_proto::Database_communication_configuration();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::parkspace_proto::Database_communication_configuration::InitAsDefaultInstance();
+}
+
+void InitDefaultsDatabase_communication_configuration() {
+  static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
+  ::google::protobuf::GoogleOnceInit(&once, &InitDefaultsDatabase_communication_configurationImpl);
+}
+
+void InitDefaultsDatabase_communication_configuration_allImpl() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+#ifdef GOOGLE_PROTOBUF_ENFORCE_UNIQUENESS
+  ::google::protobuf::internal::InitProtobufDefaultsForceUnique();
+#else
+  ::google::protobuf::internal::InitProtobufDefaults();
+#endif  // GOOGLE_PROTOBUF_ENFORCE_UNIQUENESS
+  protobuf_database_5fcommunication_5fconfiguration_2eproto::InitDefaultsDatabase_communication_configuration();
+  {
+    void* ptr = &::parkspace_proto::_Database_communication_configuration_all_default_instance_;
+    new (ptr) ::parkspace_proto::Database_communication_configuration_all();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::parkspace_proto::Database_communication_configuration_all::InitAsDefaultInstance();
+}
+
+void InitDefaultsDatabase_communication_configuration_all() {
+  static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
+  ::google::protobuf::GoogleOnceInit(&once, &InitDefaultsDatabase_communication_configuration_allImpl);
+}
+
+::google::protobuf::Metadata file_level_metadata[2];
+
+const ::google::protobuf::uint32 TableStruct::offsets[] GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
+  GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::parkspace_proto::Database_communication_configuration, _has_bits_),
+  GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::parkspace_proto::Database_communication_configuration, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::parkspace_proto::Database_communication_configuration, db_ip_),
+  GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::parkspace_proto::Database_communication_configuration, db_port_),
+  GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::parkspace_proto::Database_communication_configuration, db_username_),
+  GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::parkspace_proto::Database_communication_configuration, db_passwd_),
+  GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::parkspace_proto::Database_communication_configuration, db_name_),
+  GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::parkspace_proto::Database_communication_configuration, db_conn_pool_size_),
+  0,
+  4,
+  1,
+  2,
+  3,
+  5,
+  GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::parkspace_proto::Database_communication_configuration_all, _has_bits_),
+  GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::parkspace_proto::Database_communication_configuration_all, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::parkspace_proto::Database_communication_configuration_all, database_communication_configurations_),
+  0,
+};
+static const ::google::protobuf::internal::MigrationSchema schemas[] GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
+  { 0, 11, sizeof(::parkspace_proto::Database_communication_configuration)},
+  { 17, 23, sizeof(::parkspace_proto::Database_communication_configuration_all)},
+};
+
+static ::google::protobuf::Message const * const file_default_instances[] = {
+  reinterpret_cast<const ::google::protobuf::Message*>(&::parkspace_proto::_Database_communication_configuration_default_instance_),
+  reinterpret_cast<const ::google::protobuf::Message*>(&::parkspace_proto::_Database_communication_configuration_all_default_instance_),
+};
+
+void protobuf_AssignDescriptors() {
+  AddDescriptors();
+  ::google::protobuf::MessageFactory* factory = NULL;
+  AssignDescriptors(
+      "database_communication_configuration.proto", schemas, file_default_instances, TableStruct::offsets, factory,
+      file_level_metadata, NULL, NULL);
+}
+
+void protobuf_AssignDescriptorsOnce() {
+  static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
+  ::google::protobuf::GoogleOnceInit(&once, &protobuf_AssignDescriptors);
+}
+
+void protobuf_RegisterTypes(const ::std::string&) GOOGLE_PROTOBUF_ATTRIBUTE_COLD;
+void protobuf_RegisterTypes(const ::std::string&) {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::internal::RegisterAllTypes(file_level_metadata, 2);
+}
+
+void AddDescriptorsImpl() {
+  InitDefaults();
+  static const char descriptor[] GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
+      "\n*database_communication_configuration.p"
+      "roto\022\017parkspace_proto\"\234\001\n$Database_commu"
+      "nication_configuration\022\r\n\005db_ip\030\001 \002(\t\022\017\n"
+      "\007db_port\030\002 \002(\003\022\023\n\013db_username\030\003 \002(\t\022\023\n\td"
+      "b_passwd\030\004 \001(\t:\000\022\017\n\007db_name\030\005 \002(\t\022\031\n\021db_"
+      "conn_pool_size\030\006 \001(\003\"\220\001\n(Database_commun"
+      "ication_configuration_all\022d\n%database_co"
+      "mmunication_configurations\030\001 \001(\01325.parks"
+      "pace_proto.Database_communication_config"
+      "uration"
+  };
+  ::google::protobuf::DescriptorPool::InternalAddGeneratedFile(
+      descriptor, 367);
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
+    "database_communication_configuration.proto", &protobuf_RegisterTypes);
+}
+
+void AddDescriptors() {
+  static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
+  ::google::protobuf::GoogleOnceInit(&once, &AddDescriptorsImpl);
+}
+// Force AddDescriptors() to be called at dynamic initialization time.
+struct StaticDescriptorInitializer {
+  StaticDescriptorInitializer() {
+    AddDescriptors();
+  }
+} static_descriptor_initializer;
+}  // namespace protobuf_database_5fcommunication_5fconfiguration_2eproto
+namespace parkspace_proto {
+
+// ===================================================================
+
+void Database_communication_configuration::InitAsDefaultInstance() {
+}
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int Database_communication_configuration::kDbIpFieldNumber;
+const int Database_communication_configuration::kDbPortFieldNumber;
+const int Database_communication_configuration::kDbUsernameFieldNumber;
+const int Database_communication_configuration::kDbPasswdFieldNumber;
+const int Database_communication_configuration::kDbNameFieldNumber;
+const int Database_communication_configuration::kDbConnPoolSizeFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+Database_communication_configuration::Database_communication_configuration()
+  : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+  if (GOOGLE_PREDICT_TRUE(this != internal_default_instance())) {
+    ::protobuf_database_5fcommunication_5fconfiguration_2eproto::InitDefaultsDatabase_communication_configuration();
+  }
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:parkspace_proto.Database_communication_configuration)
+}
+Database_communication_configuration::Database_communication_configuration(const Database_communication_configuration& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(NULL),
+      _has_bits_(from._has_bits_),
+      _cached_size_(0) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  db_ip_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (from.has_db_ip()) {
+    db_ip_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.db_ip_);
+  }
+  db_username_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (from.has_db_username()) {
+    db_username_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.db_username_);
+  }
+  db_passwd_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (from.has_db_passwd()) {
+    db_passwd_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.db_passwd_);
+  }
+  db_name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (from.has_db_name()) {
+    db_name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.db_name_);
+  }
+  ::memcpy(&db_port_, &from.db_port_,
+    static_cast<size_t>(reinterpret_cast<char*>(&db_conn_pool_size_) -
+    reinterpret_cast<char*>(&db_port_)) + sizeof(db_conn_pool_size_));
+  // @@protoc_insertion_point(copy_constructor:parkspace_proto.Database_communication_configuration)
+}
+
+void Database_communication_configuration::SharedCtor() {
+  _cached_size_ = 0;
+  db_ip_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  db_username_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  db_passwd_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  db_name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  ::memset(&db_port_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&db_conn_pool_size_) -
+      reinterpret_cast<char*>(&db_port_)) + sizeof(db_conn_pool_size_));
+}
+
+Database_communication_configuration::~Database_communication_configuration() {
+  // @@protoc_insertion_point(destructor:parkspace_proto.Database_communication_configuration)
+  SharedDtor();
+}
+
+void Database_communication_configuration::SharedDtor() {
+  db_ip_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  db_username_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  db_passwd_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  db_name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+
+void Database_communication_configuration::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* Database_communication_configuration::descriptor() {
+  ::protobuf_database_5fcommunication_5fconfiguration_2eproto::protobuf_AssignDescriptorsOnce();
+  return ::protobuf_database_5fcommunication_5fconfiguration_2eproto::file_level_metadata[kIndexInFileMessages].descriptor;
+}
+
+const Database_communication_configuration& Database_communication_configuration::default_instance() {
+  ::protobuf_database_5fcommunication_5fconfiguration_2eproto::InitDefaultsDatabase_communication_configuration();
+  return *internal_default_instance();
+}
+
+Database_communication_configuration* Database_communication_configuration::New(::google::protobuf::Arena* arena) const {
+  Database_communication_configuration* n = new Database_communication_configuration;
+  if (arena != NULL) {
+    arena->Own(n);
+  }
+  return n;
+}
+
+void Database_communication_configuration::Clear() {
+// @@protoc_insertion_point(message_clear_start:parkspace_proto.Database_communication_configuration)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  cached_has_bits = _has_bits_[0];
+  if (cached_has_bits & 15u) {
+    if (cached_has_bits & 0x00000001u) {
+      GOOGLE_DCHECK(!db_ip_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()));
+      (*db_ip_.UnsafeRawStringPointer())->clear();
+    }
+    if (cached_has_bits & 0x00000002u) {
+      GOOGLE_DCHECK(!db_username_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()));
+      (*db_username_.UnsafeRawStringPointer())->clear();
+    }
+    if (cached_has_bits & 0x00000004u) {
+      GOOGLE_DCHECK(!db_passwd_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()));
+      (*db_passwd_.UnsafeRawStringPointer())->clear();
+    }
+    if (cached_has_bits & 0x00000008u) {
+      GOOGLE_DCHECK(!db_name_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()));
+      (*db_name_.UnsafeRawStringPointer())->clear();
+    }
+  }
+  if (cached_has_bits & 48u) {
+    ::memset(&db_port_, 0, static_cast<size_t>(
+        reinterpret_cast<char*>(&db_conn_pool_size_) -
+        reinterpret_cast<char*>(&db_port_)) + sizeof(db_conn_pool_size_));
+  }
+  _has_bits_.Clear();
+  _internal_metadata_.Clear();
+}
+
+bool Database_communication_configuration::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:parkspace_proto.Database_communication_configuration)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // required string db_ip = 1;
+      case 1: {
+        if (static_cast< ::google::protobuf::uint8>(tag) ==
+            static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_db_ip()));
+          ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+            this->db_ip().data(), static_cast<int>(this->db_ip().length()),
+            ::google::protobuf::internal::WireFormat::PARSE,
+            "parkspace_proto.Database_communication_configuration.db_ip");
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // required int64 db_port = 2;
+      case 2: {
+        if (static_cast< ::google::protobuf::uint8>(tag) ==
+            static_cast< ::google::protobuf::uint8>(16u /* 16 & 0xFF */)) {
+          set_has_db_port();
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::int64, ::google::protobuf::internal::WireFormatLite::TYPE_INT64>(
+                 input, &db_port_)));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // required string db_username = 3;
+      case 3: {
+        if (static_cast< ::google::protobuf::uint8>(tag) ==
+            static_cast< ::google::protobuf::uint8>(26u /* 26 & 0xFF */)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_db_username()));
+          ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+            this->db_username().data(), static_cast<int>(this->db_username().length()),
+            ::google::protobuf::internal::WireFormat::PARSE,
+            "parkspace_proto.Database_communication_configuration.db_username");
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // optional string db_passwd = 4 [default = ""];
+      case 4: {
+        if (static_cast< ::google::protobuf::uint8>(tag) ==
+            static_cast< ::google::protobuf::uint8>(34u /* 34 & 0xFF */)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_db_passwd()));
+          ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+            this->db_passwd().data(), static_cast<int>(this->db_passwd().length()),
+            ::google::protobuf::internal::WireFormat::PARSE,
+            "parkspace_proto.Database_communication_configuration.db_passwd");
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // required string db_name = 5;
+      case 5: {
+        if (static_cast< ::google::protobuf::uint8>(tag) ==
+            static_cast< ::google::protobuf::uint8>(42u /* 42 & 0xFF */)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_db_name()));
+          ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+            this->db_name().data(), static_cast<int>(this->db_name().length()),
+            ::google::protobuf::internal::WireFormat::PARSE,
+            "parkspace_proto.Database_communication_configuration.db_name");
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // optional int64 db_conn_pool_size = 6;
+      case 6: {
+        if (static_cast< ::google::protobuf::uint8>(tag) ==
+            static_cast< ::google::protobuf::uint8>(48u /* 48 & 0xFF */)) {
+          set_has_db_conn_pool_size();
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::int64, ::google::protobuf::internal::WireFormatLite::TYPE_INT64>(
+                 input, &db_conn_pool_size_)));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:parkspace_proto.Database_communication_configuration)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:parkspace_proto.Database_communication_configuration)
+  return false;
+#undef DO_
+}
+
+void Database_communication_configuration::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:parkspace_proto.Database_communication_configuration)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  cached_has_bits = _has_bits_[0];
+  // required string db_ip = 1;
+  if (cached_has_bits & 0x00000001u) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->db_ip().data(), static_cast<int>(this->db_ip().length()),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "parkspace_proto.Database_communication_configuration.db_ip");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      1, this->db_ip(), output);
+  }
+
+  // required int64 db_port = 2;
+  if (cached_has_bits & 0x00000010u) {
+    ::google::protobuf::internal::WireFormatLite::WriteInt64(2, this->db_port(), output);
+  }
+
+  // required string db_username = 3;
+  if (cached_has_bits & 0x00000002u) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->db_username().data(), static_cast<int>(this->db_username().length()),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "parkspace_proto.Database_communication_configuration.db_username");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      3, this->db_username(), output);
+  }
+
+  // optional string db_passwd = 4 [default = ""];
+  if (cached_has_bits & 0x00000004u) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->db_passwd().data(), static_cast<int>(this->db_passwd().length()),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "parkspace_proto.Database_communication_configuration.db_passwd");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      4, this->db_passwd(), output);
+  }
+
+  // required string db_name = 5;
+  if (cached_has_bits & 0x00000008u) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->db_name().data(), static_cast<int>(this->db_name().length()),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "parkspace_proto.Database_communication_configuration.db_name");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      5, this->db_name(), output);
+  }
+
+  // optional int64 db_conn_pool_size = 6;
+  if (cached_has_bits & 0x00000020u) {
+    ::google::protobuf::internal::WireFormatLite::WriteInt64(6, this->db_conn_pool_size(), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:parkspace_proto.Database_communication_configuration)
+}
+
+::google::protobuf::uint8* Database_communication_configuration::InternalSerializeWithCachedSizesToArray(
+    bool deterministic, ::google::protobuf::uint8* target) const {
+  (void)deterministic; // Unused
+  // @@protoc_insertion_point(serialize_to_array_start:parkspace_proto.Database_communication_configuration)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  cached_has_bits = _has_bits_[0];
+  // required string db_ip = 1;
+  if (cached_has_bits & 0x00000001u) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->db_ip().data(), static_cast<int>(this->db_ip().length()),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "parkspace_proto.Database_communication_configuration.db_ip");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        1, this->db_ip(), target);
+  }
+
+  // required int64 db_port = 2;
+  if (cached_has_bits & 0x00000010u) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteInt64ToArray(2, this->db_port(), target);
+  }
+
+  // required string db_username = 3;
+  if (cached_has_bits & 0x00000002u) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->db_username().data(), static_cast<int>(this->db_username().length()),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "parkspace_proto.Database_communication_configuration.db_username");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        3, this->db_username(), target);
+  }
+
+  // optional string db_passwd = 4 [default = ""];
+  if (cached_has_bits & 0x00000004u) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->db_passwd().data(), static_cast<int>(this->db_passwd().length()),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "parkspace_proto.Database_communication_configuration.db_passwd");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        4, this->db_passwd(), target);
+  }
+
+  // required string db_name = 5;
+  if (cached_has_bits & 0x00000008u) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->db_name().data(), static_cast<int>(this->db_name().length()),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "parkspace_proto.Database_communication_configuration.db_name");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        5, this->db_name(), target);
+  }
+
+  // optional int64 db_conn_pool_size = 6;
+  if (cached_has_bits & 0x00000020u) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteInt64ToArray(6, this->db_conn_pool_size(), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:parkspace_proto.Database_communication_configuration)
+  return target;
+}
+
+size_t Database_communication_configuration::RequiredFieldsByteSizeFallback() const {
+// @@protoc_insertion_point(required_fields_byte_size_fallback_start:parkspace_proto.Database_communication_configuration)
+  size_t total_size = 0;
+
+  if (has_db_ip()) {
+    // required string db_ip = 1;
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->db_ip());
+  }
+
+  if (has_db_username()) {
+    // required string db_username = 3;
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->db_username());
+  }
+
+  if (has_db_name()) {
+    // required string db_name = 5;
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->db_name());
+  }
+
+  if (has_db_port()) {
+    // required int64 db_port = 2;
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::Int64Size(
+        this->db_port());
+  }
+
+  return total_size;
+}
+size_t Database_communication_configuration::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:parkspace_proto.Database_communication_configuration)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  if (((_has_bits_[0] & 0x0000001b) ^ 0x0000001b) == 0) {  // All required fields are present.
+    // required string db_ip = 1;
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->db_ip());
+
+    // required string db_username = 3;
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->db_username());
+
+    // required string db_name = 5;
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->db_name());
+
+    // required int64 db_port = 2;
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::Int64Size(
+        this->db_port());
+
+  } else {
+    total_size += RequiredFieldsByteSizeFallback();
+  }
+  // optional string db_passwd = 4 [default = ""];
+  if (has_db_passwd()) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->db_passwd());
+  }
+
+  // optional int64 db_conn_pool_size = 6;
+  if (has_db_conn_pool_size()) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::Int64Size(
+        this->db_conn_pool_size());
+  }
+
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = cached_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void Database_communication_configuration::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:parkspace_proto.Database_communication_configuration)
+  GOOGLE_DCHECK_NE(&from, this);
+  const Database_communication_configuration* source =
+      ::google::protobuf::internal::DynamicCastToGenerated<const Database_communication_configuration>(
+          &from);
+  if (source == NULL) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:parkspace_proto.Database_communication_configuration)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:parkspace_proto.Database_communication_configuration)
+    MergeFrom(*source);
+  }
+}
+
+void Database_communication_configuration::MergeFrom(const Database_communication_configuration& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:parkspace_proto.Database_communication_configuration)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  cached_has_bits = from._has_bits_[0];
+  if (cached_has_bits & 63u) {
+    if (cached_has_bits & 0x00000001u) {
+      set_has_db_ip();
+      db_ip_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.db_ip_);
+    }
+    if (cached_has_bits & 0x00000002u) {
+      set_has_db_username();
+      db_username_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.db_username_);
+    }
+    if (cached_has_bits & 0x00000004u) {
+      set_has_db_passwd();
+      db_passwd_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.db_passwd_);
+    }
+    if (cached_has_bits & 0x00000008u) {
+      set_has_db_name();
+      db_name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.db_name_);
+    }
+    if (cached_has_bits & 0x00000010u) {
+      db_port_ = from.db_port_;
+    }
+    if (cached_has_bits & 0x00000020u) {
+      db_conn_pool_size_ = from.db_conn_pool_size_;
+    }
+    _has_bits_[0] |= cached_has_bits;
+  }
+}
+
+void Database_communication_configuration::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:parkspace_proto.Database_communication_configuration)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void Database_communication_configuration::CopyFrom(const Database_communication_configuration& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:parkspace_proto.Database_communication_configuration)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool Database_communication_configuration::IsInitialized() const {
+  if ((_has_bits_[0] & 0x0000001b) != 0x0000001b) return false;
+  return true;
+}
+
+void Database_communication_configuration::Swap(Database_communication_configuration* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void Database_communication_configuration::InternalSwap(Database_communication_configuration* other) {
+  using std::swap;
+  db_ip_.Swap(&other->db_ip_);
+  db_username_.Swap(&other->db_username_);
+  db_passwd_.Swap(&other->db_passwd_);
+  db_name_.Swap(&other->db_name_);
+  swap(db_port_, other->db_port_);
+  swap(db_conn_pool_size_, other->db_conn_pool_size_);
+  swap(_has_bits_[0], other->_has_bits_[0]);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata Database_communication_configuration::GetMetadata() const {
+  protobuf_database_5fcommunication_5fconfiguration_2eproto::protobuf_AssignDescriptorsOnce();
+  return ::protobuf_database_5fcommunication_5fconfiguration_2eproto::file_level_metadata[kIndexInFileMessages];
+}
+
+
+// ===================================================================
+
+void Database_communication_configuration_all::InitAsDefaultInstance() {
+  ::parkspace_proto::_Database_communication_configuration_all_default_instance_._instance.get_mutable()->database_communication_configurations_ = const_cast< ::parkspace_proto::Database_communication_configuration*>(
+      ::parkspace_proto::Database_communication_configuration::internal_default_instance());
+}
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int Database_communication_configuration_all::kDatabaseCommunicationConfigurationsFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+Database_communication_configuration_all::Database_communication_configuration_all()
+  : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+  if (GOOGLE_PREDICT_TRUE(this != internal_default_instance())) {
+    ::protobuf_database_5fcommunication_5fconfiguration_2eproto::InitDefaultsDatabase_communication_configuration_all();
+  }
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:parkspace_proto.Database_communication_configuration_all)
+}
+Database_communication_configuration_all::Database_communication_configuration_all(const Database_communication_configuration_all& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(NULL),
+      _has_bits_(from._has_bits_),
+      _cached_size_(0) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  if (from.has_database_communication_configurations()) {
+    database_communication_configurations_ = new ::parkspace_proto::Database_communication_configuration(*from.database_communication_configurations_);
+  } else {
+    database_communication_configurations_ = NULL;
+  }
+  // @@protoc_insertion_point(copy_constructor:parkspace_proto.Database_communication_configuration_all)
+}
+
+void Database_communication_configuration_all::SharedCtor() {
+  _cached_size_ = 0;
+  database_communication_configurations_ = NULL;
+}
+
+Database_communication_configuration_all::~Database_communication_configuration_all() {
+  // @@protoc_insertion_point(destructor:parkspace_proto.Database_communication_configuration_all)
+  SharedDtor();
+}
+
+void Database_communication_configuration_all::SharedDtor() {
+  if (this != internal_default_instance()) delete database_communication_configurations_;
+}
+
+void Database_communication_configuration_all::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* Database_communication_configuration_all::descriptor() {
+  ::protobuf_database_5fcommunication_5fconfiguration_2eproto::protobuf_AssignDescriptorsOnce();
+  return ::protobuf_database_5fcommunication_5fconfiguration_2eproto::file_level_metadata[kIndexInFileMessages].descriptor;
+}
+
+const Database_communication_configuration_all& Database_communication_configuration_all::default_instance() {
+  ::protobuf_database_5fcommunication_5fconfiguration_2eproto::InitDefaultsDatabase_communication_configuration_all();
+  return *internal_default_instance();
+}
+
+Database_communication_configuration_all* Database_communication_configuration_all::New(::google::protobuf::Arena* arena) const {
+  Database_communication_configuration_all* n = new Database_communication_configuration_all;
+  if (arena != NULL) {
+    arena->Own(n);
+  }
+  return n;
+}
+
+void Database_communication_configuration_all::Clear() {
+// @@protoc_insertion_point(message_clear_start:parkspace_proto.Database_communication_configuration_all)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  cached_has_bits = _has_bits_[0];
+  if (cached_has_bits & 0x00000001u) {
+    GOOGLE_DCHECK(database_communication_configurations_ != NULL);
+    database_communication_configurations_->Clear();
+  }
+  _has_bits_.Clear();
+  _internal_metadata_.Clear();
+}
+
+bool Database_communication_configuration_all::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:parkspace_proto.Database_communication_configuration_all)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // optional .parkspace_proto.Database_communication_configuration database_communication_configurations = 1;
+      case 1: {
+        if (static_cast< ::google::protobuf::uint8>(tag) ==
+            static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+               input, mutable_database_communication_configurations()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:parkspace_proto.Database_communication_configuration_all)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:parkspace_proto.Database_communication_configuration_all)
+  return false;
+#undef DO_
+}
+
+void Database_communication_configuration_all::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:parkspace_proto.Database_communication_configuration_all)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  cached_has_bits = _has_bits_[0];
+  // optional .parkspace_proto.Database_communication_configuration database_communication_configurations = 1;
+  if (cached_has_bits & 0x00000001u) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      1, *this->database_communication_configurations_, output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:parkspace_proto.Database_communication_configuration_all)
+}
+
+::google::protobuf::uint8* Database_communication_configuration_all::InternalSerializeWithCachedSizesToArray(
+    bool deterministic, ::google::protobuf::uint8* target) const {
+  (void)deterministic; // Unused
+  // @@protoc_insertion_point(serialize_to_array_start:parkspace_proto.Database_communication_configuration_all)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  cached_has_bits = _has_bits_[0];
+  // optional .parkspace_proto.Database_communication_configuration database_communication_configurations = 1;
+  if (cached_has_bits & 0x00000001u) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        1, *this->database_communication_configurations_, deterministic, target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:parkspace_proto.Database_communication_configuration_all)
+  return target;
+}
+
+size_t Database_communication_configuration_all::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:parkspace_proto.Database_communication_configuration_all)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  // optional .parkspace_proto.Database_communication_configuration database_communication_configurations = 1;
+  if (has_database_communication_configurations()) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::MessageSize(
+        *this->database_communication_configurations_);
+  }
+
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = cached_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void Database_communication_configuration_all::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:parkspace_proto.Database_communication_configuration_all)
+  GOOGLE_DCHECK_NE(&from, this);
+  const Database_communication_configuration_all* source =
+      ::google::protobuf::internal::DynamicCastToGenerated<const Database_communication_configuration_all>(
+          &from);
+  if (source == NULL) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:parkspace_proto.Database_communication_configuration_all)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:parkspace_proto.Database_communication_configuration_all)
+    MergeFrom(*source);
+  }
+}
+
+void Database_communication_configuration_all::MergeFrom(const Database_communication_configuration_all& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:parkspace_proto.Database_communication_configuration_all)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  if (from.has_database_communication_configurations()) {
+    mutable_database_communication_configurations()->::parkspace_proto::Database_communication_configuration::MergeFrom(from.database_communication_configurations());
+  }
+}
+
+void Database_communication_configuration_all::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:parkspace_proto.Database_communication_configuration_all)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void Database_communication_configuration_all::CopyFrom(const Database_communication_configuration_all& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:parkspace_proto.Database_communication_configuration_all)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool Database_communication_configuration_all::IsInitialized() const {
+  if (has_database_communication_configurations()) {
+    if (!this->database_communication_configurations_->IsInitialized()) return false;
+  }
+  return true;
+}
+
+void Database_communication_configuration_all::Swap(Database_communication_configuration_all* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void Database_communication_configuration_all::InternalSwap(Database_communication_configuration_all* other) {
+  using std::swap;
+  swap(database_communication_configurations_, other->database_communication_configurations_);
+  swap(_has_bits_[0], other->_has_bits_[0]);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata Database_communication_configuration_all::GetMetadata() const {
+  protobuf_database_5fcommunication_5fconfiguration_2eproto::protobuf_AssignDescriptorsOnce();
+  return ::protobuf_database_5fcommunication_5fconfiguration_2eproto::file_level_metadata[kIndexInFileMessages];
+}
+
+
+// @@protoc_insertion_point(namespace_scope)
+}  // namespace parkspace_proto
+
+// @@protoc_insertion_point(global_scope)

+ 752 - 0
plc调度节点/dispatch/database_communication_configuration.pb.h

@@ -0,0 +1,752 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: database_communication_configuration.proto
+
+#ifndef PROTOBUF_database_5fcommunication_5fconfiguration_2eproto__INCLUDED
+#define PROTOBUF_database_5fcommunication_5fconfiguration_2eproto__INCLUDED
+
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+
+#if GOOGLE_PROTOBUF_VERSION < 3005000
+#error This file was generated by a newer version of protoc which is
+#error incompatible with your Protocol Buffer headers.  Please update
+#error your headers.
+#endif
+#if 3005000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
+#error This file was generated by an older version of protoc which is
+#error incompatible with your Protocol Buffer headers.  Please
+#error regenerate this file with a newer version of protoc.
+#endif
+
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/arena.h>
+#include <google/protobuf/arenastring.h>
+#include <google/protobuf/generated_message_table_driven.h>
+#include <google/protobuf/generated_message_util.h>
+#include <google/protobuf/metadata.h>
+#include <google/protobuf/message.h>
+#include <google/protobuf/repeated_field.h>  // IWYU pragma: export
+#include <google/protobuf/extension_set.h>  // IWYU pragma: export
+#include <google/protobuf/unknown_field_set.h>
+// @@protoc_insertion_point(includes)
+
+namespace protobuf_database_5fcommunication_5fconfiguration_2eproto {
+// Internal implementation detail -- do not use these members.
+struct TableStruct {
+  static const ::google::protobuf::internal::ParseTableField entries[];
+  static const ::google::protobuf::internal::AuxillaryParseTableField aux[];
+  static const ::google::protobuf::internal::ParseTable schema[2];
+  static const ::google::protobuf::internal::FieldMetadata field_metadata[];
+  static const ::google::protobuf::internal::SerializationTable serialization_table[];
+  static const ::google::protobuf::uint32 offsets[];
+};
+void AddDescriptors();
+void InitDefaultsDatabase_communication_configurationImpl();
+void InitDefaultsDatabase_communication_configuration();
+void InitDefaultsDatabase_communication_configuration_allImpl();
+void InitDefaultsDatabase_communication_configuration_all();
+inline void InitDefaults() {
+  InitDefaultsDatabase_communication_configuration();
+  InitDefaultsDatabase_communication_configuration_all();
+}
+}  // namespace protobuf_database_5fcommunication_5fconfiguration_2eproto
+namespace parkspace_proto {
+class Database_communication_configuration;
+class Database_communication_configurationDefaultTypeInternal;
+extern Database_communication_configurationDefaultTypeInternal _Database_communication_configuration_default_instance_;
+class Database_communication_configuration_all;
+class Database_communication_configuration_allDefaultTypeInternal;
+extern Database_communication_configuration_allDefaultTypeInternal _Database_communication_configuration_all_default_instance_;
+}  // namespace parkspace_proto
+namespace parkspace_proto {
+
+// ===================================================================
+
+class Database_communication_configuration : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:parkspace_proto.Database_communication_configuration) */ {
+ public:
+  Database_communication_configuration();
+  virtual ~Database_communication_configuration();
+
+  Database_communication_configuration(const Database_communication_configuration& from);
+
+  inline Database_communication_configuration& operator=(const Database_communication_configuration& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  Database_communication_configuration(Database_communication_configuration&& from) noexcept
+    : Database_communication_configuration() {
+    *this = ::std::move(from);
+  }
+
+  inline Database_communication_configuration& operator=(Database_communication_configuration&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
+    return _internal_metadata_.unknown_fields();
+  }
+  inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
+    return _internal_metadata_.mutable_unknown_fields();
+  }
+
+  static const ::google::protobuf::Descriptor* descriptor();
+  static const Database_communication_configuration& default_instance();
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const Database_communication_configuration* internal_default_instance() {
+    return reinterpret_cast<const Database_communication_configuration*>(
+               &_Database_communication_configuration_default_instance_);
+  }
+  static PROTOBUF_CONSTEXPR int const kIndexInFileMessages =
+    0;
+
+  void Swap(Database_communication_configuration* other);
+  friend void swap(Database_communication_configuration& a, Database_communication_configuration& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline Database_communication_configuration* New() const PROTOBUF_FINAL { return New(NULL); }
+
+  Database_communication_configuration* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL;
+  void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL;
+  void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL;
+  void CopyFrom(const Database_communication_configuration& from);
+  void MergeFrom(const Database_communication_configuration& from);
+  void Clear() PROTOBUF_FINAL;
+  bool IsInitialized() const PROTOBUF_FINAL;
+
+  size_t ByteSizeLong() const PROTOBUF_FINAL;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) PROTOBUF_FINAL;
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const PROTOBUF_FINAL;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      bool deterministic, ::google::protobuf::uint8* target) const PROTOBUF_FINAL;
+  int GetCachedSize() const PROTOBUF_FINAL { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const PROTOBUF_FINAL;
+  void InternalSwap(Database_communication_configuration* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return NULL;
+  }
+  inline void* MaybeArenaPtr() const {
+    return NULL;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const PROTOBUF_FINAL;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // required string db_ip = 1;
+  bool has_db_ip() const;
+  void clear_db_ip();
+  static const int kDbIpFieldNumber = 1;
+  const ::std::string& db_ip() const;
+  void set_db_ip(const ::std::string& value);
+  #if LANG_CXX11
+  void set_db_ip(::std::string&& value);
+  #endif
+  void set_db_ip(const char* value);
+  void set_db_ip(const char* value, size_t size);
+  ::std::string* mutable_db_ip();
+  ::std::string* release_db_ip();
+  void set_allocated_db_ip(::std::string* db_ip);
+
+  // required string db_username = 3;
+  bool has_db_username() const;
+  void clear_db_username();
+  static const int kDbUsernameFieldNumber = 3;
+  const ::std::string& db_username() const;
+  void set_db_username(const ::std::string& value);
+  #if LANG_CXX11
+  void set_db_username(::std::string&& value);
+  #endif
+  void set_db_username(const char* value);
+  void set_db_username(const char* value, size_t size);
+  ::std::string* mutable_db_username();
+  ::std::string* release_db_username();
+  void set_allocated_db_username(::std::string* db_username);
+
+  // optional string db_passwd = 4 [default = ""];
+  bool has_db_passwd() const;
+  void clear_db_passwd();
+  static const int kDbPasswdFieldNumber = 4;
+  const ::std::string& db_passwd() const;
+  void set_db_passwd(const ::std::string& value);
+  #if LANG_CXX11
+  void set_db_passwd(::std::string&& value);
+  #endif
+  void set_db_passwd(const char* value);
+  void set_db_passwd(const char* value, size_t size);
+  ::std::string* mutable_db_passwd();
+  ::std::string* release_db_passwd();
+  void set_allocated_db_passwd(::std::string* db_passwd);
+
+  // required string db_name = 5;
+  bool has_db_name() const;
+  void clear_db_name();
+  static const int kDbNameFieldNumber = 5;
+  const ::std::string& db_name() const;
+  void set_db_name(const ::std::string& value);
+  #if LANG_CXX11
+  void set_db_name(::std::string&& value);
+  #endif
+  void set_db_name(const char* value);
+  void set_db_name(const char* value, size_t size);
+  ::std::string* mutable_db_name();
+  ::std::string* release_db_name();
+  void set_allocated_db_name(::std::string* db_name);
+
+  // required int64 db_port = 2;
+  bool has_db_port() const;
+  void clear_db_port();
+  static const int kDbPortFieldNumber = 2;
+  ::google::protobuf::int64 db_port() const;
+  void set_db_port(::google::protobuf::int64 value);
+
+  // optional int64 db_conn_pool_size = 6;
+  bool has_db_conn_pool_size() const;
+  void clear_db_conn_pool_size();
+  static const int kDbConnPoolSizeFieldNumber = 6;
+  ::google::protobuf::int64 db_conn_pool_size() const;
+  void set_db_conn_pool_size(::google::protobuf::int64 value);
+
+  // @@protoc_insertion_point(class_scope:parkspace_proto.Database_communication_configuration)
+ private:
+  void set_has_db_ip();
+  void clear_has_db_ip();
+  void set_has_db_port();
+  void clear_has_db_port();
+  void set_has_db_username();
+  void clear_has_db_username();
+  void set_has_db_passwd();
+  void clear_has_db_passwd();
+  void set_has_db_name();
+  void clear_has_db_name();
+  void set_has_db_conn_pool_size();
+  void clear_has_db_conn_pool_size();
+
+  // helper for ByteSizeLong()
+  size_t RequiredFieldsByteSizeFallback() const;
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::internal::HasBits<1> _has_bits_;
+  mutable int _cached_size_;
+  ::google::protobuf::internal::ArenaStringPtr db_ip_;
+  ::google::protobuf::internal::ArenaStringPtr db_username_;
+  ::google::protobuf::internal::ArenaStringPtr db_passwd_;
+  ::google::protobuf::internal::ArenaStringPtr db_name_;
+  ::google::protobuf::int64 db_port_;
+  ::google::protobuf::int64 db_conn_pool_size_;
+  friend struct ::protobuf_database_5fcommunication_5fconfiguration_2eproto::TableStruct;
+  friend void ::protobuf_database_5fcommunication_5fconfiguration_2eproto::InitDefaultsDatabase_communication_configurationImpl();
+};
+// -------------------------------------------------------------------
+
+class Database_communication_configuration_all : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:parkspace_proto.Database_communication_configuration_all) */ {
+ public:
+  Database_communication_configuration_all();
+  virtual ~Database_communication_configuration_all();
+
+  Database_communication_configuration_all(const Database_communication_configuration_all& from);
+
+  inline Database_communication_configuration_all& operator=(const Database_communication_configuration_all& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  Database_communication_configuration_all(Database_communication_configuration_all&& from) noexcept
+    : Database_communication_configuration_all() {
+    *this = ::std::move(from);
+  }
+
+  inline Database_communication_configuration_all& operator=(Database_communication_configuration_all&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
+    return _internal_metadata_.unknown_fields();
+  }
+  inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
+    return _internal_metadata_.mutable_unknown_fields();
+  }
+
+  static const ::google::protobuf::Descriptor* descriptor();
+  static const Database_communication_configuration_all& default_instance();
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const Database_communication_configuration_all* internal_default_instance() {
+    return reinterpret_cast<const Database_communication_configuration_all*>(
+               &_Database_communication_configuration_all_default_instance_);
+  }
+  static PROTOBUF_CONSTEXPR int const kIndexInFileMessages =
+    1;
+
+  void Swap(Database_communication_configuration_all* other);
+  friend void swap(Database_communication_configuration_all& a, Database_communication_configuration_all& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline Database_communication_configuration_all* New() const PROTOBUF_FINAL { return New(NULL); }
+
+  Database_communication_configuration_all* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL;
+  void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL;
+  void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL;
+  void CopyFrom(const Database_communication_configuration_all& from);
+  void MergeFrom(const Database_communication_configuration_all& from);
+  void Clear() PROTOBUF_FINAL;
+  bool IsInitialized() const PROTOBUF_FINAL;
+
+  size_t ByteSizeLong() const PROTOBUF_FINAL;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) PROTOBUF_FINAL;
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const PROTOBUF_FINAL;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      bool deterministic, ::google::protobuf::uint8* target) const PROTOBUF_FINAL;
+  int GetCachedSize() const PROTOBUF_FINAL { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const PROTOBUF_FINAL;
+  void InternalSwap(Database_communication_configuration_all* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return NULL;
+  }
+  inline void* MaybeArenaPtr() const {
+    return NULL;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const PROTOBUF_FINAL;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // optional .parkspace_proto.Database_communication_configuration database_communication_configurations = 1;
+  bool has_database_communication_configurations() const;
+  void clear_database_communication_configurations();
+  static const int kDatabaseCommunicationConfigurationsFieldNumber = 1;
+  const ::parkspace_proto::Database_communication_configuration& database_communication_configurations() const;
+  ::parkspace_proto::Database_communication_configuration* release_database_communication_configurations();
+  ::parkspace_proto::Database_communication_configuration* mutable_database_communication_configurations();
+  void set_allocated_database_communication_configurations(::parkspace_proto::Database_communication_configuration* database_communication_configurations);
+
+  // @@protoc_insertion_point(class_scope:parkspace_proto.Database_communication_configuration_all)
+ private:
+  void set_has_database_communication_configurations();
+  void clear_has_database_communication_configurations();
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::internal::HasBits<1> _has_bits_;
+  mutable int _cached_size_;
+  ::parkspace_proto::Database_communication_configuration* database_communication_configurations_;
+  friend struct ::protobuf_database_5fcommunication_5fconfiguration_2eproto::TableStruct;
+  friend void ::protobuf_database_5fcommunication_5fconfiguration_2eproto::InitDefaultsDatabase_communication_configuration_allImpl();
+};
+// ===================================================================
+
+
+// ===================================================================
+
+#ifdef __GNUC__
+  #pragma GCC diagnostic push
+  #pragma GCC diagnostic ignored "-Wstrict-aliasing"
+#endif  // __GNUC__
+// Database_communication_configuration
+
+// required string db_ip = 1;
+inline bool Database_communication_configuration::has_db_ip() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void Database_communication_configuration::set_has_db_ip() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void Database_communication_configuration::clear_has_db_ip() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+inline void Database_communication_configuration::clear_db_ip() {
+  db_ip_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_db_ip();
+}
+inline const ::std::string& Database_communication_configuration::db_ip() const {
+  // @@protoc_insertion_point(field_get:parkspace_proto.Database_communication_configuration.db_ip)
+  return db_ip_.GetNoArena();
+}
+inline void Database_communication_configuration::set_db_ip(const ::std::string& value) {
+  set_has_db_ip();
+  db_ip_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:parkspace_proto.Database_communication_configuration.db_ip)
+}
+#if LANG_CXX11
+inline void Database_communication_configuration::set_db_ip(::std::string&& value) {
+  set_has_db_ip();
+  db_ip_.SetNoArena(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
+  // @@protoc_insertion_point(field_set_rvalue:parkspace_proto.Database_communication_configuration.db_ip)
+}
+#endif
+inline void Database_communication_configuration::set_db_ip(const char* value) {
+  GOOGLE_DCHECK(value != NULL);
+  set_has_db_ip();
+  db_ip_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:parkspace_proto.Database_communication_configuration.db_ip)
+}
+inline void Database_communication_configuration::set_db_ip(const char* value, size_t size) {
+  set_has_db_ip();
+  db_ip_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:parkspace_proto.Database_communication_configuration.db_ip)
+}
+inline ::std::string* Database_communication_configuration::mutable_db_ip() {
+  set_has_db_ip();
+  // @@protoc_insertion_point(field_mutable:parkspace_proto.Database_communication_configuration.db_ip)
+  return db_ip_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* Database_communication_configuration::release_db_ip() {
+  // @@protoc_insertion_point(field_release:parkspace_proto.Database_communication_configuration.db_ip)
+  clear_has_db_ip();
+  return db_ip_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Database_communication_configuration::set_allocated_db_ip(::std::string* db_ip) {
+  if (db_ip != NULL) {
+    set_has_db_ip();
+  } else {
+    clear_has_db_ip();
+  }
+  db_ip_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), db_ip);
+  // @@protoc_insertion_point(field_set_allocated:parkspace_proto.Database_communication_configuration.db_ip)
+}
+
+// required int64 db_port = 2;
+inline bool Database_communication_configuration::has_db_port() const {
+  return (_has_bits_[0] & 0x00000010u) != 0;
+}
+inline void Database_communication_configuration::set_has_db_port() {
+  _has_bits_[0] |= 0x00000010u;
+}
+inline void Database_communication_configuration::clear_has_db_port() {
+  _has_bits_[0] &= ~0x00000010u;
+}
+inline void Database_communication_configuration::clear_db_port() {
+  db_port_ = GOOGLE_LONGLONG(0);
+  clear_has_db_port();
+}
+inline ::google::protobuf::int64 Database_communication_configuration::db_port() const {
+  // @@protoc_insertion_point(field_get:parkspace_proto.Database_communication_configuration.db_port)
+  return db_port_;
+}
+inline void Database_communication_configuration::set_db_port(::google::protobuf::int64 value) {
+  set_has_db_port();
+  db_port_ = value;
+  // @@protoc_insertion_point(field_set:parkspace_proto.Database_communication_configuration.db_port)
+}
+
+// required string db_username = 3;
+inline bool Database_communication_configuration::has_db_username() const {
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+inline void Database_communication_configuration::set_has_db_username() {
+  _has_bits_[0] |= 0x00000002u;
+}
+inline void Database_communication_configuration::clear_has_db_username() {
+  _has_bits_[0] &= ~0x00000002u;
+}
+inline void Database_communication_configuration::clear_db_username() {
+  db_username_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_db_username();
+}
+inline const ::std::string& Database_communication_configuration::db_username() const {
+  // @@protoc_insertion_point(field_get:parkspace_proto.Database_communication_configuration.db_username)
+  return db_username_.GetNoArena();
+}
+inline void Database_communication_configuration::set_db_username(const ::std::string& value) {
+  set_has_db_username();
+  db_username_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:parkspace_proto.Database_communication_configuration.db_username)
+}
+#if LANG_CXX11
+inline void Database_communication_configuration::set_db_username(::std::string&& value) {
+  set_has_db_username();
+  db_username_.SetNoArena(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
+  // @@protoc_insertion_point(field_set_rvalue:parkspace_proto.Database_communication_configuration.db_username)
+}
+#endif
+inline void Database_communication_configuration::set_db_username(const char* value) {
+  GOOGLE_DCHECK(value != NULL);
+  set_has_db_username();
+  db_username_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:parkspace_proto.Database_communication_configuration.db_username)
+}
+inline void Database_communication_configuration::set_db_username(const char* value, size_t size) {
+  set_has_db_username();
+  db_username_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:parkspace_proto.Database_communication_configuration.db_username)
+}
+inline ::std::string* Database_communication_configuration::mutable_db_username() {
+  set_has_db_username();
+  // @@protoc_insertion_point(field_mutable:parkspace_proto.Database_communication_configuration.db_username)
+  return db_username_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* Database_communication_configuration::release_db_username() {
+  // @@protoc_insertion_point(field_release:parkspace_proto.Database_communication_configuration.db_username)
+  clear_has_db_username();
+  return db_username_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Database_communication_configuration::set_allocated_db_username(::std::string* db_username) {
+  if (db_username != NULL) {
+    set_has_db_username();
+  } else {
+    clear_has_db_username();
+  }
+  db_username_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), db_username);
+  // @@protoc_insertion_point(field_set_allocated:parkspace_proto.Database_communication_configuration.db_username)
+}
+
+// optional string db_passwd = 4 [default = ""];
+inline bool Database_communication_configuration::has_db_passwd() const {
+  return (_has_bits_[0] & 0x00000004u) != 0;
+}
+inline void Database_communication_configuration::set_has_db_passwd() {
+  _has_bits_[0] |= 0x00000004u;
+}
+inline void Database_communication_configuration::clear_has_db_passwd() {
+  _has_bits_[0] &= ~0x00000004u;
+}
+inline void Database_communication_configuration::clear_db_passwd() {
+  db_passwd_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_db_passwd();
+}
+inline const ::std::string& Database_communication_configuration::db_passwd() const {
+  // @@protoc_insertion_point(field_get:parkspace_proto.Database_communication_configuration.db_passwd)
+  return db_passwd_.GetNoArena();
+}
+inline void Database_communication_configuration::set_db_passwd(const ::std::string& value) {
+  set_has_db_passwd();
+  db_passwd_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:parkspace_proto.Database_communication_configuration.db_passwd)
+}
+#if LANG_CXX11
+inline void Database_communication_configuration::set_db_passwd(::std::string&& value) {
+  set_has_db_passwd();
+  db_passwd_.SetNoArena(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
+  // @@protoc_insertion_point(field_set_rvalue:parkspace_proto.Database_communication_configuration.db_passwd)
+}
+#endif
+inline void Database_communication_configuration::set_db_passwd(const char* value) {
+  GOOGLE_DCHECK(value != NULL);
+  set_has_db_passwd();
+  db_passwd_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:parkspace_proto.Database_communication_configuration.db_passwd)
+}
+inline void Database_communication_configuration::set_db_passwd(const char* value, size_t size) {
+  set_has_db_passwd();
+  db_passwd_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:parkspace_proto.Database_communication_configuration.db_passwd)
+}
+inline ::std::string* Database_communication_configuration::mutable_db_passwd() {
+  set_has_db_passwd();
+  // @@protoc_insertion_point(field_mutable:parkspace_proto.Database_communication_configuration.db_passwd)
+  return db_passwd_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* Database_communication_configuration::release_db_passwd() {
+  // @@protoc_insertion_point(field_release:parkspace_proto.Database_communication_configuration.db_passwd)
+  clear_has_db_passwd();
+  return db_passwd_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Database_communication_configuration::set_allocated_db_passwd(::std::string* db_passwd) {
+  if (db_passwd != NULL) {
+    set_has_db_passwd();
+  } else {
+    clear_has_db_passwd();
+  }
+  db_passwd_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), db_passwd);
+  // @@protoc_insertion_point(field_set_allocated:parkspace_proto.Database_communication_configuration.db_passwd)
+}
+
+// required string db_name = 5;
+inline bool Database_communication_configuration::has_db_name() const {
+  return (_has_bits_[0] & 0x00000008u) != 0;
+}
+inline void Database_communication_configuration::set_has_db_name() {
+  _has_bits_[0] |= 0x00000008u;
+}
+inline void Database_communication_configuration::clear_has_db_name() {
+  _has_bits_[0] &= ~0x00000008u;
+}
+inline void Database_communication_configuration::clear_db_name() {
+  db_name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_db_name();
+}
+inline const ::std::string& Database_communication_configuration::db_name() const {
+  // @@protoc_insertion_point(field_get:parkspace_proto.Database_communication_configuration.db_name)
+  return db_name_.GetNoArena();
+}
+inline void Database_communication_configuration::set_db_name(const ::std::string& value) {
+  set_has_db_name();
+  db_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:parkspace_proto.Database_communication_configuration.db_name)
+}
+#if LANG_CXX11
+inline void Database_communication_configuration::set_db_name(::std::string&& value) {
+  set_has_db_name();
+  db_name_.SetNoArena(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
+  // @@protoc_insertion_point(field_set_rvalue:parkspace_proto.Database_communication_configuration.db_name)
+}
+#endif
+inline void Database_communication_configuration::set_db_name(const char* value) {
+  GOOGLE_DCHECK(value != NULL);
+  set_has_db_name();
+  db_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:parkspace_proto.Database_communication_configuration.db_name)
+}
+inline void Database_communication_configuration::set_db_name(const char* value, size_t size) {
+  set_has_db_name();
+  db_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:parkspace_proto.Database_communication_configuration.db_name)
+}
+inline ::std::string* Database_communication_configuration::mutable_db_name() {
+  set_has_db_name();
+  // @@protoc_insertion_point(field_mutable:parkspace_proto.Database_communication_configuration.db_name)
+  return db_name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* Database_communication_configuration::release_db_name() {
+  // @@protoc_insertion_point(field_release:parkspace_proto.Database_communication_configuration.db_name)
+  clear_has_db_name();
+  return db_name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Database_communication_configuration::set_allocated_db_name(::std::string* db_name) {
+  if (db_name != NULL) {
+    set_has_db_name();
+  } else {
+    clear_has_db_name();
+  }
+  db_name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), db_name);
+  // @@protoc_insertion_point(field_set_allocated:parkspace_proto.Database_communication_configuration.db_name)
+}
+
+// optional int64 db_conn_pool_size = 6;
+inline bool Database_communication_configuration::has_db_conn_pool_size() const {
+  return (_has_bits_[0] & 0x00000020u) != 0;
+}
+inline void Database_communication_configuration::set_has_db_conn_pool_size() {
+  _has_bits_[0] |= 0x00000020u;
+}
+inline void Database_communication_configuration::clear_has_db_conn_pool_size() {
+  _has_bits_[0] &= ~0x00000020u;
+}
+inline void Database_communication_configuration::clear_db_conn_pool_size() {
+  db_conn_pool_size_ = GOOGLE_LONGLONG(0);
+  clear_has_db_conn_pool_size();
+}
+inline ::google::protobuf::int64 Database_communication_configuration::db_conn_pool_size() const {
+  // @@protoc_insertion_point(field_get:parkspace_proto.Database_communication_configuration.db_conn_pool_size)
+  return db_conn_pool_size_;
+}
+inline void Database_communication_configuration::set_db_conn_pool_size(::google::protobuf::int64 value) {
+  set_has_db_conn_pool_size();
+  db_conn_pool_size_ = value;
+  // @@protoc_insertion_point(field_set:parkspace_proto.Database_communication_configuration.db_conn_pool_size)
+}
+
+// -------------------------------------------------------------------
+
+// Database_communication_configuration_all
+
+// optional .parkspace_proto.Database_communication_configuration database_communication_configurations = 1;
+inline bool Database_communication_configuration_all::has_database_communication_configurations() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void Database_communication_configuration_all::set_has_database_communication_configurations() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void Database_communication_configuration_all::clear_has_database_communication_configurations() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+inline void Database_communication_configuration_all::clear_database_communication_configurations() {
+  if (database_communication_configurations_ != NULL) database_communication_configurations_->Clear();
+  clear_has_database_communication_configurations();
+}
+inline const ::parkspace_proto::Database_communication_configuration& Database_communication_configuration_all::database_communication_configurations() const {
+  const ::parkspace_proto::Database_communication_configuration* p = database_communication_configurations_;
+  // @@protoc_insertion_point(field_get:parkspace_proto.Database_communication_configuration_all.database_communication_configurations)
+  return p != NULL ? *p : *reinterpret_cast<const ::parkspace_proto::Database_communication_configuration*>(
+      &::parkspace_proto::_Database_communication_configuration_default_instance_);
+}
+inline ::parkspace_proto::Database_communication_configuration* Database_communication_configuration_all::release_database_communication_configurations() {
+  // @@protoc_insertion_point(field_release:parkspace_proto.Database_communication_configuration_all.database_communication_configurations)
+  clear_has_database_communication_configurations();
+  ::parkspace_proto::Database_communication_configuration* temp = database_communication_configurations_;
+  database_communication_configurations_ = NULL;
+  return temp;
+}
+inline ::parkspace_proto::Database_communication_configuration* Database_communication_configuration_all::mutable_database_communication_configurations() {
+  set_has_database_communication_configurations();
+  if (database_communication_configurations_ == NULL) {
+    database_communication_configurations_ = new ::parkspace_proto::Database_communication_configuration;
+  }
+  // @@protoc_insertion_point(field_mutable:parkspace_proto.Database_communication_configuration_all.database_communication_configurations)
+  return database_communication_configurations_;
+}
+inline void Database_communication_configuration_all::set_allocated_database_communication_configurations(::parkspace_proto::Database_communication_configuration* database_communication_configurations) {
+  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
+  if (message_arena == NULL) {
+    delete database_communication_configurations_;
+  }
+  if (database_communication_configurations) {
+    ::google::protobuf::Arena* submessage_arena = NULL;
+    if (message_arena != submessage_arena) {
+      database_communication_configurations = ::google::protobuf::internal::GetOwnedMessage(
+          message_arena, database_communication_configurations, submessage_arena);
+    }
+    set_has_database_communication_configurations();
+  } else {
+    clear_has_database_communication_configurations();
+  }
+  database_communication_configurations_ = database_communication_configurations;
+  // @@protoc_insertion_point(field_set_allocated:parkspace_proto.Database_communication_configuration_all.database_communication_configurations)
+}
+
+#ifdef __GNUC__
+  #pragma GCC diagnostic pop
+#endif  // __GNUC__
+// -------------------------------------------------------------------
+
+
+// @@protoc_insertion_point(namespace_scope)
+
+}  // namespace parkspace_proto
+
+// @@protoc_insertion_point(global_scope)
+
+#endif  // PROTOBUF_database_5fcommunication_5fconfiguration_2eproto__INCLUDED

+ 18 - 0
plc调度节点/dispatch/database_communication_configuration.proto

@@ -0,0 +1,18 @@
+syntax = "proto2";
+package parkspace_proto;
+
+message Database_communication_configuration
+{
+    required string db_ip=1;
+    required int64 db_port=2;
+    required string db_username=3;
+    optional string db_passwd=4[default=""];
+    required string db_name=5;
+    optional int64 db_conn_pool_size=6;
+}
+
+message Database_communication_configuration_all
+{
+    optional Database_communication_configuration   database_communication_configurations = 1;
+}
+

+ 572 - 0
plc调度节点/dispatch/database_controller.cpp

@@ -0,0 +1,572 @@
+/*
+ * @Description: 数据库操作类
+ * @Author: yct
+ * @Date: 2020-07-15 14:08:46
+ * @LastEditTime: 2020-07-24 14:19:31
+ * @LastEditors: yct
+ */
+
+#include "database_controller.h"
+
+Database_controller::Database_controller()
+{
+	m_database_controller_status = E_UNKNOWN;
+	mp_reconnect_thread = nullptr;
+	m_conn_pool_size = 0;
+}
+
+
+Database_controller::~Database_controller()
+{
+	database_controller_uninit();
+}
+
+
+Error_manager Database_controller::database_controller_init()
+{
+	return database_controller_init_from_protobuf(DATABASE_COMMUNICATION_PARAMETER_PATH);
+}
+Error_manager Database_controller::database_controller_init_from_protobuf(std::string prototxt_path)
+{
+	parkspace_proto::Database_communication_configuration_all t_database_config;
+	if(!  proto_tool::read_proto_param(prototxt_path,t_database_config) )
+	{
+		return Error_manager(DB_PROTOBUF_ERROR,MINOR_ERROR,
+							 "database_controller_init_from_protobuf(std::string prototxt_path) failed");
+	}
+	else
+	{
+		Error_manager t_error;
+		t_error=database_controller_init(t_database_config.database_communication_configurations().db_ip(),\
+										t_database_config.database_communication_configurations().db_port(),\
+										t_database_config.database_communication_configurations().db_username(),\
+										t_database_config.database_communication_configurations().db_passwd(),\
+										t_database_config.database_communication_configurations().db_name(),\
+										t_database_config.database_communication_configurations().db_conn_pool_size());
+		if ( t_error != Error_code::SUCCESS )
+		{
+			return t_error;
+		}
+	}
+	return SUCCESS;
+}
+//初始化
+Error_manager Database_controller::database_controller_init(std::string ip, int port, std::string username, std::string pass, std::string db_name, int conn_size)
+{
+	Error_manager t_error;
+
+	//系统结束标记与连接池大小
+//    mb_exit = false;
+	m_conn_pool_size = conn_size;
+	m_db_param.connect_string = std::string("tcp://").append(ip).append(":").append(std::to_string(port));
+	m_db_param.username = username;
+	m_db_param.pass = pass;
+	m_db_param.db_name = db_name;
+	if(sql::mysql::get_driver_instance() == nullptr)
+	{
+		//胡力 直接修改状态
+		m_database_controller_status = E_FAULT;
+
+//        mb_initialized = false;
+		return DB_INIT_FAILED;
+		return Error_manager(Error_code::DB_INIT_FAILED, Error_level::MAJOR_ERROR,
+							"数据库初始化失败 Database_controller::database_controller_init error ");
+	}
+	////创建补充 数据库连接的通路
+	t_error = fill_up_connect_channel();
+
+
+	//守护线程,检查连接状态并保持连接数量
+
+
+	m_database_reconnect_condition.reset(false,false,false);
+	mp_reconnect_thread = new std::thread(&Database_controller::database_reconnect_thread, this);
+
+	return t_error;
+}
+
+//反初始化
+Error_manager Database_controller::database_controller_uninit()
+{
+//    mb_exit = true;
+	if(mp_reconnect_thread!=nullptr)
+	{
+		m_database_reconnect_condition.kill_all();
+	}
+	if(mp_reconnect_thread!=nullptr)
+	{
+		if(mp_reconnect_thread->joinable())
+			mp_reconnect_thread->join();
+		delete mp_reconnect_thread;
+		mp_reconnect_thread = nullptr;
+	}
+
+	m_database_connect_channel_list.clear();
+
+	return SUCCESS;
+}
+Database_controller::Database_controller_status Database_controller::get_database_controller_status()
+{
+	return m_database_controller_status;
+}
+Error_manager Database_controller::check_status()
+{
+	if(get_database_controller_status()==E_READY)
+	{
+		return SUCCESS;
+	}
+	else if(get_database_controller_status() == E_UNKNOWN)
+	{
+		return Error_manager(Error_code::DB_INIT_FAILED, Error_level::MINOR_ERROR,
+							 "数据库初始化失败 check_status() error ");
+	}
+	else if(get_database_controller_status() == E_DISCONNECT)
+	{
+		return Error_manager(Error_code::DB_CONNECT_FAILED, Error_level::MINOR_ERROR,
+							 "数据库连接失败 check_status() error ");
+	}
+	else if(get_database_controller_status() == E_FAULT)
+	{
+		return Error_manager(Error_code::DB_STATUS_ERROR, Error_level::MINOR_ERROR,
+							 "数据库状态错误 check_status() error ");
+	}
+
+}
+//数据库连接状态
+bool Database_controller::is_connected()
+{
+	if ( m_database_controller_status == E_READY)
+	{
+		return true;
+	}
+	else
+	{
+		return false;
+	}
+//
+//    updata_connect_channel();
+//    return mb_connected;
+}
+
+//****** 增删改查功能 *******
+//增
+Error_manager Database_controller::sql_insert(std::string sql_str)
+{
+#ifdef COUT_SQL_STRING
+	LOG(INFO) << " sql_str =  "<< sql_str << " --- " << this;
+#endif
+	Error_manager t_error;
+	//huli
+	t_error = check_status();
+	if ( t_error != Error_code::SUCCESS )
+	{
+		return t_error;
+	}
+	boost::shared_ptr<Database_connect_channel> tp_database_connect_channel;
+	t_error = occupancy_connect_channel(tp_database_connect_channel);
+	if ( t_error != Error_code::SUCCESS )
+	{
+		return t_error;
+	}
+
+	char buf[1024];
+	memset(buf, 0, 1024);
+	try
+	{
+		tp_database_connect_channel->mp_connect_channel->setSchema(m_db_param.db_name);
+		boost::scoped_ptr<sql::Statement> stmt(tp_database_connect_channel->mp_connect_channel->createStatement());
+		stmt->execute(sql_str);
+
+		giveback_connect_channel(tp_database_connect_channel);
+		return SUCCESS;
+	}
+	catch (sql::SQLException &e)
+	{
+		giveback_connect_channel(tp_database_connect_channel);
+		/* Use what() (derived from std::runtime_error) to fetch the error message */
+		sprintf(buf, "# ERR: %s\n (MySQL error code: %d, SQLState: %s\nsql: %s", e.what(), e.getErrorCode(), e.getSQLState().c_str(), sql_str.c_str());
+		usleep(1000* 3000);
+		return Error_manager(DB_INSERT_FAILED, NEGLIGIBLE_ERROR, buf);
+	}
+	catch (std::runtime_error &e)
+	{
+		giveback_connect_channel(tp_database_connect_channel);
+		sprintf(buf, "# ERR: %s\n ERR: runtime_error in  %s \nsql: %s",e.what(),__FILE__, sql_str.c_str());
+		return Error_manager(DB_INSERT_FAILED, NEGLIGIBLE_ERROR, buf);
+	}
+	// catch (std::exception &e)
+	// {
+	//     sprintf(buf, "# ERR: %s\n ERR: Standard exception in  %s ",e.what(),__FILE__);
+	//     return Error_manager(DB_INSERT_FAILED, NEGLIGIBLE_ERROR, buf);
+	// }
+	
+	return SUCCESS;
+}
+
+//删
+Error_manager Database_controller::sql_delete(std::string sql_str)
+{
+#ifdef COUT_SQL_STRING
+	LOG(INFO) << " sql_str =  "<< sql_str << " --- " << this;
+#endif
+	// 1.检查状态,一旦无可用连接,则主动创建一个,若依然失败则直接返回错误
+	Error_manager t_error;
+	//huli
+	t_error = check_status();
+	if ( t_error != Error_code::SUCCESS )
+	{
+		return t_error;
+	}
+	boost::shared_ptr<Database_connect_channel> tp_database_connect_channel;
+	t_error = occupancy_connect_channel(tp_database_connect_channel);
+	if ( t_error != Error_code::SUCCESS )
+	{
+		return t_error;
+	}
+	char buf[1024];
+	memset(buf, 0, 1024);
+	try
+	{
+		tp_database_connect_channel->mp_connect_channel->setSchema(m_db_param.db_name);
+		boost::scoped_ptr<sql::Statement> stmt(tp_database_connect_channel->mp_connect_channel->createStatement());
+		stmt->execute(sql_str);
+		giveback_connect_channel(tp_database_connect_channel);
+		return SUCCESS;
+	}
+	catch (sql::SQLException &e)
+	{
+		/* Use what() (derived from std::runtime_error) to fetch the error message */
+		giveback_connect_channel(tp_database_connect_channel);
+		sprintf(buf, "# ERR: %s\n (MySQL error code: %d, SQLState: %s\nsql: %s", e.what(), e.getErrorCode(), e.getSQLState().c_str(), sql_str.c_str());
+		return Error_manager(DB_DELETE_FAILED, NEGLIGIBLE_ERROR, buf);
+	}
+	catch (std::runtime_error &e)
+	{
+		giveback_connect_channel(tp_database_connect_channel);
+		sprintf(buf, "# ERR: %s\n ERR: runtime_error in  %s \nsql: %s",e.what(),__FILE__, sql_str.c_str());
+		return Error_manager(DB_DELETE_FAILED, NEGLIGIBLE_ERROR, buf);
+	}
+
+	return SUCCESS;
+}
+
+//改
+Error_manager Database_controller::sql_update(std::string sql_str)
+{
+#ifdef COUT_SQL_STRING
+	LOG(INFO) << " sql_str =  "<< sql_str << " --- " << this;
+#endif
+	Error_manager t_error;
+	//huli
+	t_error = check_status();
+	if ( t_error != Error_code::SUCCESS )
+	{
+		return t_error;
+	}
+	boost::shared_ptr<Database_connect_channel> tp_database_connect_channel;
+	t_error = occupancy_connect_channel(tp_database_connect_channel);
+	if ( t_error != Error_code::SUCCESS )
+	{
+		return t_error;
+	}
+	char buf[1024];
+	memset(buf, 0, 1024);
+	try
+	{
+		tp_database_connect_channel->mp_connect_channel->setSchema(m_db_param.db_name);
+		boost::scoped_ptr<sql::Statement> stmt(tp_database_connect_channel->mp_connect_channel->createStatement());
+		int affected_rows = stmt->executeUpdate(sql_str);
+		giveback_connect_channel(tp_database_connect_channel);
+		if (affected_rows > 0)
+		{
+			return SUCCESS;
+		}
+		else
+		{
+			return Error_manager(Error_code::DB_UPDATE_FAILED, Error_level::MINOR_ERROR,
+                                 (std::string("数据库修改失败 Database_controller::sql_update error ")+sql_str).c_str());
+		}
+	}
+	catch (sql::SQLException &e)
+	{
+		/* Use what() (derived from std::runtime_error) to fetch the error message */
+		giveback_connect_channel(tp_database_connect_channel);
+		sprintf(buf, "# ERR: %s\n (MySQL error code: %d, SQLState: %s\nsql: %s", e.what(), e.getErrorCode(), e.getSQLState().c_str(), sql_str.c_str());
+		return Error_manager(DB_UPDATE_FAILED, NEGLIGIBLE_ERROR, buf);
+	}
+	catch (std::runtime_error &e)
+	{
+		giveback_connect_channel(tp_database_connect_channel);
+		sprintf(buf, "# ERR: %s\n ERR: runtime_error in  %s \nsql: %s",e.what(),__FILE__, sql_str.c_str());
+		return Error_manager(DB_UPDATE_FAILED, NEGLIGIBLE_ERROR, buf);
+	}
+
+	return SUCCESS;
+}
+
+//查
+Error_manager Database_controller::sql_query(std::string sql_str, boost::shared_ptr< sql::ResultSet > &query_result)
+{
+#ifdef COUT_SQL_STRING
+	LOG(INFO) << " sql_str =  "<< sql_str << " --- " << this;
+#endif
+	Error_manager t_error;
+	//huli
+	t_error = check_status();
+	if ( t_error != Error_code::SUCCESS )
+	{
+		return t_error;
+	}
+
+	boost::shared_ptr<Database_connect_channel>  tp_database_connect_channel;
+	t_error = occupancy_connect_channel(tp_database_connect_channel);
+	if ( t_error != Error_code::SUCCESS )
+	{
+		return t_error;
+	}
+
+	char buf[1024];
+	memset(buf, 0, 1024);
+	try
+	{
+		tp_database_connect_channel->mp_connect_channel->setSchema(m_db_param.db_name);
+		boost::scoped_ptr<sql::Statement> stmt(tp_database_connect_channel->mp_connect_channel->createStatement());
+		query_result = boost::shared_ptr< sql::ResultSet >(stmt->executeQuery(sql_str));
+
+		giveback_connect_channel(tp_database_connect_channel);
+		// 检查结果
+		if(query_result==nullptr)
+		{
+			return Error_manager(Error_code::DB_QUERY_FAILED, Error_level::MAJOR_ERROR,
+                                 (std::string("数据库查询失败 Database_controller::sql_query error ")+sql_str).c_str());
+		}
+	}
+	catch (sql::SQLException &e)
+	{
+		/* Use what() (derived from std::runtime_error) to fetch the error message */
+		giveback_connect_channel(tp_database_connect_channel);
+		sprintf(buf, "# ERR: %s\n (MySQL error code: %d, SQLState: %s\nsql: %s", e.what(), e.getErrorCode(), e.getSQLState().c_str(), sql_str.c_str());
+		return Error_manager(DB_UPDATE_FAILED, NEGLIGIBLE_ERROR, buf);
+	}
+	catch (std::runtime_error &e)
+	{
+		giveback_connect_channel(tp_database_connect_channel);
+		sprintf(buf, "# ERR: %s\n ERR: runtime_error in  %s \nsql: %s",e.what(),__FILE__, sql_str.c_str());
+		return Error_manager(DB_UPDATE_FAILED, NEGLIGIBLE_ERROR, buf);
+	}
+	return SUCCESS;
+}
+
+Error_manager Database_controller::sql_control(std::string sql_str)
+{
+#ifdef COUT_SQL_STRING
+	LOG(INFO) << " sql_str =  "<< sql_str << " --- " << this;
+#endif
+	Error_manager t_error;
+	//huli
+	t_error = check_status();
+	if ( t_error != Error_code::SUCCESS )
+	{
+		return t_error;
+	}
+	boost::shared_ptr<Database_connect_channel> tp_database_connect_channel;
+	t_error = occupancy_connect_channel(tp_database_connect_channel);
+	if ( t_error != Error_code::SUCCESS )
+	{
+		return t_error;
+	}
+	char buf[1024];
+	memset(buf, 0, 1024);
+	try
+	{
+		tp_database_connect_channel->mp_connect_channel->setSchema(m_db_param.db_name);
+		boost::scoped_ptr<sql::Statement> stmt(tp_database_connect_channel->mp_connect_channel->createStatement());
+		stmt->execute(sql_str);
+		giveback_connect_channel(tp_database_connect_channel);
+		return SUCCESS;
+	}
+	catch (sql::SQLException &e)
+	{
+		giveback_connect_channel(tp_database_connect_channel);
+		sprintf(buf, "# ERR: %s\n (MySQL error code: %d, SQLState: %s\nsql: %s", e.what(), e.getErrorCode(), e.getSQLState().c_str(), sql_str.c_str());
+		return Error_manager(DB_CONTROL_FAILED, NEGLIGIBLE_ERROR, buf);
+	}
+	catch (std::runtime_error &e)
+	{
+		giveback_connect_channel(tp_database_connect_channel);
+		sprintf(buf, "# ERR: %s\n ERR: runtime_error in  %s \nsql: %s",e.what(),__FILE__, sql_str.c_str());
+		return Error_manager(DB_CONTROL_FAILED, NEGLIGIBLE_ERROR, buf);
+	}
+
+	return SUCCESS;
+}
+
+void Database_controller::database_reconnect_thread()
+{
+	//hili   这个用条件变量去控制
+
+	while (m_database_reconnect_condition.is_alive())
+	{
+		m_database_reconnect_condition.wait_for_ex(std::chrono::seconds(1));
+		if (m_database_reconnect_condition.is_alive())
+		{
+			updata_connect_channel();
+			fill_up_connect_channel();
+		}
+	}
+}
+
+// 检查连接状态
+Error_manager Database_controller::updata_connect_channel()
+{
+	for (auto iter = m_database_connect_channel_list.begin(); iter != m_database_connect_channel_list.end();)
+    {
+		if ((*iter)->mp_connect_channel == nullptr)
+		{
+			iter = m_database_connect_channel_list.erase(iter);
+		}
+		else if ( (*iter)->m_occupancy_lock.try_lock() )
+		{
+			if( (*iter)->mp_connect_channel->isValid() )
+			{
+				(*iter)->m_occupancy_lock.unlock();
+				++iter;
+			}
+			else
+			{
+				(*iter)->m_occupancy_lock.unlock();
+				iter = m_database_connect_channel_list.erase(iter);
+			}
+
+		}
+		else
+		{
+			++iter;
+		}
+    }
+    return Error_code::SUCCESS;
+}
+
+////创建补充 数据库连接的通路
+Error_manager Database_controller::fill_up_connect_channel()
+{
+	if ( m_conn_pool_size <=0 )
+	{
+	    return Error_manager(Error_code::DB_CONNECT_CHANNEL_NUMBER_ERROR, Error_level::MINOR_ERROR,
+	    					"数据库连接通道数量错误 Database_controller::fill_up_connect_channel() error ");
+	}
+
+	// 填充连接池
+	int retry_count = DB_RECONNECTION_NUMBER;
+
+	//胡力 建议修改如下
+	while (m_database_connect_channel_list.size() < m_conn_pool_size && retry_count > 0)
+	{
+		try
+		{
+
+			//胡力  数据库连接的指针   建议改名 tp_sql_connnect
+			boost::shared_ptr<sql::Connection> tp_connect_channel(sql::mysql::get_driver_instance()->connect(m_db_param.connect_string, m_db_param.username, m_db_param.pass));
+
+			if (tp_connect_channel != nullptr && tp_connect_channel->isValid())
+			{
+				boost::shared_ptr<Database_connect_channel> tp_database_connect_channel(new Database_connect_channel);
+				tp_database_connect_channel->mp_connect_channel = tp_connect_channel;
+//				tp_database_connect_channel->m_occupancy_lock.unlock();
+
+				m_database_connect_channel_list.push_back(tp_database_connect_channel);
+			}
+			else
+			{
+				retry_count--;
+			}
+
+		}
+		catch (sql::SQLException &e)
+		{
+			char buf[1024];
+			memset(buf, 0, 1024);
+			sprintf(buf, "# ERR: %s\n (MySQL error code: %d, SQLState: %s", e.what(), e.getErrorCode(), e.getSQLState().c_str());
+			retry_count--;
+		}
+	}
+
+	if ( retry_count <= 0 )
+	{
+		m_database_controller_status = E_DISCONNECT;
+		//胡力 如果报错 队列中部分成功要回收处理    需要讨论!!!!!!!!!!!!!!!!!!
+		m_database_connect_channel_list.clear();
+
+		return Error_manager(Error_code::DB_CONNECT_FAILED, Error_level::MINOR_ERROR,
+							"数据库连接失败 Database_controller::fill_up_connect_channel() error ");
+
+
+	}
+	else
+	{
+		m_database_controller_status = E_READY;
+		return Error_code::SUCCESS;
+	}
+	return SUCCESS;
+
+}
+
+
+//zhan you   jieyong
+Error_manager Database_controller::occupancy_connect_channel(boost::shared_ptr<Database_connect_channel> & p_database_connect_channel)
+{
+	for (auto iter = m_database_connect_channel_list.begin(); iter != m_database_connect_channel_list.end(); ++iter)
+	{
+		if ( (*iter)->mp_connect_channel != nullptr)
+		{
+			if ( (*iter)->m_occupancy_lock.try_lock() )
+			{
+				if ( (*iter)->mp_connect_channel->isValid() )
+//				if ( !(*iter)->mp_connect_channel->isClosed() )
+				{
+					p_database_connect_channel = (*iter);
+					return Error_code::SUCCESS;
+				}
+				(*iter)->m_occupancy_lock.unlock();
+			}
+		}
+
+
+
+//
+//
+//
+//		if ( (*iter)->mp_connect_channel != nullptr && (*iter)->mp_connect_channel->isValid()  )
+//		{
+//			if ( (*iter)->m_occupancy_lock.try_lock() )
+//			{
+//				p_database_connect_channel = (*iter);
+//				return Error_code::SUCCESS;
+//			}
+//
+//		}
+	}
+
+	//if not find
+	return Error_manager(Error_code::DB_CONNECT_CHANNEL_NOT_FOUND, Error_level::MINOR_ERROR,
+						 "数据库连接通道未找到  Database_controller::occupancy_connect_channel error ");
+}
+
+//guihuan
+Error_manager Database_controller::giveback_connect_channel(boost::shared_ptr<Database_connect_channel> p_database_connect_channel)
+{
+	if ( p_database_connect_channel == nullptr )
+	{
+	    return Error_manager(Error_code::POINTER_IS_NULL, Error_level::MINOR_ERROR,
+	    					"指针为空 Database_controller::giveback_connect_channel error ");
+	}
+
+	p_database_connect_channel->m_occupancy_lock.unlock();
+	return Error_code::SUCCESS;
+}
+
+
+
+
+
+

+ 148 - 0
plc调度节点/dispatch/database_controller.h

@@ -0,0 +1,148 @@
+/*
+ * @Description: 数据库操作类
+ * @Author: yct
+ * @Date: 2020-07-14 14:09:35
+ * @LastEditTime: 2020-07-18 23:57:10
+ * @LastEditors: yct
+ */ 
+#ifndef DATABASE_CONTROLLER_HH
+#define DATABASE_CONTROLLER_HH
+
+#include <mysql_driver.h>
+#include <mysql_connection.h>
+#include <cppconn/driver.h>
+#include <cppconn/exception.h>
+#include <cppconn/resultset.h>
+#include <cppconn/statement.h>
+
+#include "../tool/singleton.h"
+#include "../tool/thread_condition.h"
+#include "../error_code/error_code.h"
+#include "./database_communication_configuration.pb.h"
+#include <stdio.h>
+#include <mutex>
+#include <queue>
+#include <thread>
+#include <atomic>
+#include <unistd.h>
+#include <string.h>
+#include <iostream>
+#include <cstddef>
+#include <boost/shared_ptr.hpp>
+#include <proto_tool.h>
+#include <glog/logging.h>
+
+
+
+#define DB_UPDATE_INTERVAL_MILLI 20000
+
+//胡力  数据库连接线路的默认个数		默认5个
+#define DB_CONNECT_QUEUE_SIZE 		5
+
+//胡力  数据库尝试重新连接的次数    默认3次
+#define DB_RECONNECTION_NUMBER 		3
+
+
+#define DATABASE_COMMUNICATION_PARAMETER_PATH "../setting/database_communication.prototxt"
+class Database_controller : public Singleton<Database_controller>
+{
+    // 子类必须把父类设定为友元函数,这样父类才能使用子类的私有构造函数。
+    friend class Singleton<Database_controller>;
+public:
+    typedef struct DB_PARAM
+    {
+        std::string connect_string;
+        std::string username;
+        std::string pass;
+        std::string db_name;
+    } db_param;
+
+	//huli 新增数据库的状态
+	enum Database_controller_status
+	{
+	    E_UNKNOWN               = 0,    //默认未知
+	    E_READY               	= 1,    //正常待机
+		E_DISCONNECT			= 2,	//断连
+	    E_FAULT					= 3,	//故障
+	};
+
+	struct Database_connect_channel
+	{
+		boost::shared_ptr< sql::Connection> 		mp_connect_channel;
+		std::mutex									m_occupancy_lock;
+	};
+
+
+private:
+	// 父类的构造函数必须保护,子类的构造函数必须私有。
+	Database_controller() ;
+public:
+    // 必须关闭拷贝构造和赋值构造,只能通过 get_instance 函数来进行操作唯一的实例。
+    Database_controller(const Database_controller &) = delete;
+    Database_controller &operator=(const Database_controller &) = delete;
+    ~Database_controller();
+
+    //初始化
+	Error_manager database_controller_init();
+	//从文本导入
+	Error_manager database_controller_init_from_protobuf(std::string prototxt_path);
+    Error_manager database_controller_init(std::string ip, int port, std::string username, std::string pass, std::string db_name, int conn_size=DB_CONNECT_QUEUE_SIZE);
+    //反初始化
+    Error_manager database_controller_uninit();
+
+
+	Database_controller_status get_database_controller_status();
+	Error_manager check_status();
+
+    //数据库连接状态
+    bool is_connected();
+    //****** 增删改查功能 *******
+    //增
+    Error_manager sql_insert(std::string sql_str);
+    //删
+    Error_manager sql_delete(std::string sql_str);
+    //改
+    Error_manager sql_update(std::string sql_str);
+    //查
+    Error_manager sql_query(std::string sql_str, boost::shared_ptr< sql::ResultSet > &query_result);
+
+
+    //控制语句 LOCK  UNLOCK COMMIT 等
+	Error_manager sql_control(std::string sql_str);
+
+private:
+    // 守护线程,维持连接数量,以及自身状态更新
+    void database_reconnect_thread();
+    // 检查gengxin连接
+    Error_manager updata_connect_channel();
+    //创建补充 数据库连接的通路
+    Error_manager fill_up_connect_channel();
+
+	//zhan you   jieyong
+	Error_manager occupancy_connect_channel(boost::shared_ptr<Database_connect_channel> & p_database_connect_channel);
+
+	//guihuan
+	Error_manager giveback_connect_channel(boost::shared_ptr<Database_connect_channel> p_database_connect_channel);
+
+private:
+
+	//huli 新增数据库的状态
+	Database_controller_status			m_database_controller_status;
+
+    //数据库连接通路的集合
+	std::list< boost::shared_ptr<Database_connect_channel> > m_database_connect_channel_list;
+
+	//维持连接数量,以及自身状态更新条件变量
+	Thread_condition m_database_reconnect_condition;
+	//重连线程
+    std::thread *mp_reconnect_thread;
+
+
+    //连接池大小
+    int m_conn_pool_size;
+    //连接参数
+    db_param m_db_param; 
+
+};
+
+#endif // !DATABASE_CONTROLLER_HH

+ 875 - 0
plc调度节点/dispatch/dispatch_command.cpp

@@ -0,0 +1,875 @@
+
+#include "dispatch_command.h"
+#include <google/protobuf/text_format.h>
+
+
+Dispatch_command::Dispatch_command()
+{
+	m_dispatch_command_status = E_DISPATCH_COMMAND_UNKNOW;
+	m_unit = 0;
+	m_device_floor = 0;
+	m_dispatch_process_type = Common_data::DISPATCH_PROCESS_TYPE_UNKNOW;
+	m_car_type = Common_data::Car_type::UNKNOW_CAR_TYPE;
+}
+
+Dispatch_command::~Dispatch_command()
+{
+
+}
+
+
+
+//调度开始前, 向数据库发送请求的相关操作, 输入 穿梭机所在的楼层, 调度id 0~2, 空闲出口id, 如果不是0,就表示有空闲的出口
+Error_manager Dispatch_command::dispatch_request_to_sql(int device_floor, int dispatch_id, int outlet_ready)
+{
+	Error_manager t_error;
+
+	m_device_floor = device_floor;
+	m_dispatch_id = dispatch_id;
+	m_unit = dispatch_id+1;
+	m_outlet_ready = outlet_ready;
+
+	//获取调度指令, 与数据库同步 command_queue
+	t_error = query_all_dispatch_command();
+	if ( t_error != Error_code::SUCCESS )
+	{
+		return t_error;
+	}
+
+	//排序
+	if ( outlet_ready == 0 )
+	{
+		//对调度指令进行排序, 选出最优解, 只比较存车
+		t_error = sort_dispatch_command_for_park();
+	}
+	else
+	{
+		//对调度指令进行排序, 选出最优解, 比较存车和取车
+		t_error = sort_dispatch_command_for_total();
+	}
+
+	if ( t_error != Error_code::SUCCESS )
+	{
+		m_dispatch_process_type = Common_data::DISPATCH_PROCESS_TYPE_UNKNOW;
+
+		//没有找到合适的指令就返回NODATA, 然后设么也不做
+		return t_error;
+	}
+	else
+	{
+		if ( m_dispatch_command_map[m_car_number_optimal].m_type == 1 )//存车
+		{
+
+			//注注注注注意了
+			//存车自带感测信息,没有车位信息, 需要查询车位表,找到空车位,补全车位信息
+			//取车自带车位信息,没有感测信息, 需要查询车辆表,补全车辆信息
+
+			//查询空闲车位最优解,    存车指令 根据调度指令最优解 获取 空闲车位最优解
+			t_error = query_dispatch_space_optimal();
+			if ( t_error != Error_code::SUCCESS )
+			{
+				update_command_queue_for_statu(3);
+				return t_error;
+			}
+			else
+			{
+				m_dispatch_process_type = Common_data::DISPATCH_PROCESS_STORE;
+
+				m_dispatch_command_map[m_car_number_optimal].m_parkspace_info_msg.set_id(m_dispatch_space_info.m_id);
+				m_dispatch_command_map[m_car_number_optimal].m_parkspace_info_msg.set_unit_id(m_dispatch_space_info.m_unit);
+				m_dispatch_command_map[m_car_number_optimal].m_parkspace_info_msg.set_floor(m_dispatch_space_info.m_floor);
+				m_dispatch_command_map[m_car_number_optimal].m_parkspace_info_msg.set_room_id(m_dispatch_space_info.m_subID);
+
+				//更新 车位状态, 根据车位ID 写入车牌号即可
+				t_error = update_parkspace_info_write_car_number();
+				//更新 指令队列, 根据车牌号 修改状态即可,  //指令状态, 0排队中, 1正在工作, 2已完成, 3故障异常
+				t_error = update_command_queue_for_statu(1);
+				//制作存车表单
+				t_error = create_park_table();
+
+				LOG(INFO) << " create_park_table 创建存车任务单 =  "<< m_park_table_msg.DebugString() << " --- " << this;
+				return Error_code::SUCCESS;
+			}
+		}
+		else if ( m_dispatch_command_map[m_car_number_optimal].m_type == 2 )//取车
+		{
+			//注注注注注意了
+			//存车自带感测信息,没有车位信息, 需要查询车位表,找到空车位,补全车位信息
+			//取车自带车位信息,没有感测信息, 需要查询车辆表,补全车辆信息
+
+			//查询 取车的车辆感测信息    取车指令 根据key 查询感测信息
+			t_error = query_dispatch_vehicle_for_primary_key();
+			if ( t_error != Error_code::SUCCESS )
+			{
+				update_command_queue_for_statu(3);
+				return t_error;
+			}
+			else
+			{
+				//补充出口id
+				m_dispatch_command_map[m_car_number_optimal].m_export_id = outlet_ready;
+
+				m_dispatch_process_type = Common_data::DISPATCH_PROCESS_PICKUP;
+
+				m_dispatch_command_map[m_car_number_optimal].m_measure_info_msg = m_dispatch_vehicle_info.m_actually_measure_info_msg;
+
+				//更新 指令队列, 根据车牌号 修改状态即可,  //指令状态, 0排队中, 1正在工作, 2已完成, 3故障异常
+				t_error = update_command_queue_for_statu(1);
+				//制作取车表单
+				t_error = create_pick_table(outlet_ready);
+				LOG(INFO) << " create_pick_table 创建取车车任务单 =  "<< m_pick_table_msg.DebugString() << " --- " << this;
+			}
+		}
+		else
+		{
+			return Error_manager(Error_code::ERROR, Error_level::MINOR_ERROR,
+								 " fun error ");
+		}
+	}
+	return Error_code::SUCCESS;
+}
+
+//调度完成后, 向数据库发送答复的相关操作
+Error_manager Dispatch_command::dispatch_response_to_sql(Error_manager dispatch_result)
+{
+	Error_manager t_error;
+
+	if ( dispatch_result == Error_code::SUCCESS )
+	{
+		//调度成功, 完善数据库
+		if ( m_dispatch_process_type == Common_data::DISPATCH_PROCESS_STORE )
+		{
+			LOG(INFO) << " dispatch_response_to_sql DISPATCH_PROCESS_STORE 存车答复成功 =  "<< t_error << " --- " << this;
+			//增加 车辆表, 存车指令 完成后添加车辆信息
+			t_error = insert_vehicle_for_car_number();
+			//更新 指令队列, 根据车牌号 删除指令
+			t_error = delete_command_queue_for_statu();
+
+		}
+		else if ( m_dispatch_process_type == Common_data::DISPATCH_PROCESS_PICKUP )
+		{
+			LOG(INFO) << " dispatch_response_to_sql DISPATCH_PROCESS_PICKUP 取车答复成功 =  "<< t_error << " --- " << this;
+
+			//删除 车辆表, 取车指令 完成后删除车辆信息
+			t_error = delete_vehicle_for_car_number();
+			//更新 车位状态, 找到车牌号, 写NULL
+			t_error = update_parkspace_info_clear_car_number();
+			//更新 指令队列, 根据车牌号 修改状态即可,  //指令状态, 0排队中, 1正在工作, 2已完成, 3故障异常
+			t_error = update_command_queue_for_statu(2);
+//			LOG(INFO) << "llllllllllllllllllllllllllllllllllllllllll respons =  "<< t_error << " --- " << this;
+		}
+		else if ( m_dispatch_process_type == Common_data::DISPATCH_PROCESS_REALLOCATE )
+		{
+			LOG(INFO) << " dispatch_response_to_sql DISPATCH_PROCESS_REALLOCATE 改道答复成功 =  "<< t_error << " --- " << this;
+			//增加 车辆表, 存车指令 完成后添加车辆信息
+			t_error = insert_vehicle_for_car_number();
+			//更新 指令队列, 根据车牌号 删除指令
+			t_error = delete_command_queue_for_statu();
+
+		}
+		else if ( m_dispatch_process_type == Common_data::DISPATCH_PROCESS_REVOCATION )
+		{
+			LOG(INFO) << " dispatch_response_to_sql DISPATCH_PROCESS_REVOCATION 撤销答复成功 =  "<< t_error << " --- " << this;
+
+			//删除 车辆表, 取车指令 完成后删除车辆信息
+			t_error = delete_vehicle_for_car_number();
+			//更新 车位状态, 找到车牌号, 写NULL
+			t_error = update_parkspace_info_clear_car_number();
+			//更新 指令队列, 根据车牌号 修改状态即可,  //指令状态, 0排队中, 1正在工作, 2已完成, 3故障异常
+			t_error = update_command_queue_for_statu(2);
+//			LOG(INFO) << "llllllllllllllllllllllllllllllllllllllllll respons =  "<< t_error << " --- " << this;
+		}
+		else
+		{
+			return Error_manager(Error_code::ERROR, Error_level::MINOR_ERROR,
+								 " fun error ");
+		}
+
+		return t_error;
+	}
+	else
+	{
+		//调度失败, 回退 数据库
+		if ( m_dispatch_process_type == Common_data::DISPATCH_PROCESS_STORE )
+		{
+			LOG(INFO) << " dispatch_response_to_sql DISPATCH_PROCESS_STORE 存车答复失败 =  "<< t_error << " --- " << this;
+			//更新 车位状态, 找到车牌号, 写NULL
+			update_parkspace_info_clear_car_number();
+			//更新 指令队列, 根据车牌号 修改状态即可,  //指令状态, 0排队中, 1正在工作, 2已完成, 3故障异常
+			update_command_queue_for_statu(3);
+		}
+		else if ( m_dispatch_process_type == Common_data::DISPATCH_PROCESS_PICKUP )
+		{
+			LOG(INFO) << " dispatch_response_to_sql DISPATCH_PROCESS_PICKUP 取车答复失败 =  "<< t_error << " --- " << this;
+			//更新 指令队列, 根据车牌号 修改状态即可,  //指令状态, 0排队中, 1正在工作, 2已完成, 3故障异常
+			update_command_queue_for_statu(3);
+		}
+		else if ( m_dispatch_process_type == Common_data::DISPATCH_PROCESS_REALLOCATE )
+		{
+			LOG(INFO) << " dispatch_response_to_sql DISPATCH_PROCESS_STORE 改道答复失败 =  "<< t_error << " --- " << this;
+			//更新 车位状态, 找到车牌号, 写NULL
+			update_parkspace_info_clear_car_number();
+			//更新 指令队列, 根据车牌号 修改状态即可,  //指令状态, 0排队中, 1正在工作, 2已完成, 3故障异常
+			update_command_queue_for_statu(3);
+		}
+		else if ( m_dispatch_process_type == Common_data::DISPATCH_PROCESS_REVOCATION )
+		{
+			LOG(INFO) << " dispatch_response_to_sql DISPATCH_PROCESS_PICKUP 撤销答复失败 =  "<< t_error << " --- " << this;
+			//更新 指令队列, 根据车牌号 修改状态即可,  //指令状态, 0排队中, 1正在工作, 2已完成, 3故障异常
+			update_command_queue_for_statu(3);
+		}
+		else
+		{
+			return Error_manager(Error_code::ERROR, Error_level::MINOR_ERROR,
+								 " fun error ");
+		}
+	}
+
+	return Error_code::SUCCESS;
+}
+
+//调度 , 向数据库 重新分配车位,
+Error_manager Dispatch_command::dispatch_reallocate_to_sql(Common_data::Car_type reallocate_car_type, int outlet_ready)
+{
+	Error_manager t_error;
+
+	m_outlet_ready = outlet_ready;
+
+	//把之前申请的车位清除  //更新 车位状态, 找到车牌号, 写NULL
+	t_error = Dispatch_command::update_parkspace_info_clear_car_number();
+
+	//重新申请车位
+	//查询空闲车位最优解,    存车指令 根据调度指令最优解 获取 空闲车位最优解
+	t_error = query_dispatch_space_optimal(reallocate_car_type);
+
+	if ( t_error != Error_code::SUCCESS )
+	{
+		//没找到车位, 就把车放到出口
+		if ( outlet_ready != 0 )
+		{
+			m_dispatch_process_type = Common_data::DISPATCH_PROCESS_REVOCATION;
+
+			//补充出口id
+			m_dispatch_command_map[m_car_number_optimal].m_export_id = outlet_ready;
+
+			m_dispatch_command_map[m_car_number_optimal].m_parkspace_info_msg.set_id(0);
+			m_dispatch_command_map[m_car_number_optimal].m_parkspace_info_msg.set_unit_id(0);
+			m_dispatch_command_map[m_car_number_optimal].m_parkspace_info_msg.set_floor(0);
+			m_dispatch_command_map[m_car_number_optimal].m_parkspace_info_msg.set_room_id(0);
+
+			//更新 指令队列, 根据车牌号 修改状态即可,  //指令状态, 0排队中, 1正在工作, 2已完成, 3故障异常
+//			t_error = update_command_queue_for_statu(1);
+			//制作取车表单
+			t_error = create_pick_table(outlet_ready);
+			LOG(INFO) << " create_pick_table 撤销存车, 取车到出口任务单 =  "<< m_pick_table_msg.DebugString() << " --- " << this;
+
+			return t_error;
+		}
+		else
+		{
+			//无限等待, 等待出口空闲
+			return Error_code::NODATA;
+		}
+	}
+	else
+	{
+		m_dispatch_process_type = Common_data::DISPATCH_PROCESS_REALLOCATE;
+
+		//找到新的车位, 重新执行任务
+		m_dispatch_command_map[m_car_number_optimal].m_parkspace_info_msg.set_id(m_dispatch_space_info.m_id);
+		m_dispatch_command_map[m_car_number_optimal].m_parkspace_info_msg.set_unit_id(m_dispatch_space_info.m_unit);
+		m_dispatch_command_map[m_car_number_optimal].m_parkspace_info_msg.set_floor(m_dispatch_space_info.m_floor);
+		m_dispatch_command_map[m_car_number_optimal].m_parkspace_info_msg.set_room_id(m_dispatch_space_info.m_subID);
+
+		//更新 车位状态, 根据车位ID 写入车牌号即可
+		t_error = update_parkspace_info_write_car_number();
+		//更新 指令队列, 根据车牌号 修改状态即可,  //指令状态, 0排队中, 1正在工作, 2已完成, 3故障异常
+//		t_error = update_command_queue_for_statu(1);
+		//制作存车表单
+		t_error = create_park_table();
+
+		LOG(INFO) << " create_park_table 改道存车, 存车新车位任务单 =  "<< m_park_table_msg.DebugString() << " --- " << this;
+	}
+
+	return Error_code::SUCCESS;
+}
+
+
+//检查出口是否空闲, 检查指令队列的取车完成的出口id是否存在, 不存在就是空闲,返回成功
+Error_manager Dispatch_command::check_export_id_is_ready(int export_id)
+{
+	//检查指令队列, 查询指定单元的取车完成状态指令的 出口id是否存在
+	char check_export_id_sql[1024];
+	memset(check_export_id_sql, 0, 1024);
+	sprintf(check_export_id_sql,"select * from command_queue where statu = 2 and export_id = %d",export_id);
+	boost::shared_ptr<sql::ResultSet>  tp_result = nullptr;
+	Error_manager t_error = Database_controller::get_instance_pointer()->sql_query(check_export_id_sql, tp_result);
+
+	if(t_error == Error_code::SUCCESS)
+	{
+		if (tp_result == nullptr)
+		{
+			return DB_RESULT_SET_EMPTY;
+		}
+
+		//如果存在, 就报错,   不存在就是空闲,返回成功
+		if ( tp_result->next() )
+		{
+			return Error_manager(Error_code::DB_QUERY_OUTLET_OCCUPY, Error_level::MINOR_ERROR,
+								 " check_export_id_is_ready fun error, 数据库 查询出口被占用 ");
+		}
+		else
+		{
+			return Error_code::SUCCESS;
+		}
+	}
+	else
+	{
+		return t_error;
+	}
+	return Error_code::SUCCESS;
+}
+
+
+
+//更新调度指令, 与数据库同步 command_queue
+Error_manager Dispatch_command::query_all_dispatch_command()
+{
+	//从command_queue获取所有排队的指令,
+	char query_all_dispatch_command_sql[1024];
+	memset(query_all_dispatch_command_sql, 0, 1024);
+	sprintf(query_all_dispatch_command_sql,"select * from command_queue where statu = 0 and unit = %d",m_unit);
+	boost::shared_ptr<sql::ResultSet>  tp_result = nullptr;
+	Error_manager t_error = Database_controller::get_instance_pointer()->sql_query(query_all_dispatch_command_sql, tp_result);
+
+	m_dispatch_command_map.clear();
+	if(t_error == Error_code::SUCCESS)
+	{
+		if (tp_result == nullptr)
+		{
+			return DB_RESULT_SET_EMPTY;
+		}
+
+		//循环检查所有行
+		while (tp_result->next())
+		{
+			Dispatch_command_info t_dispatch_command_info;
+			char t_error_buf[1024];
+			memset(t_error_buf, 0, 1024);
+			try
+			{
+				//解析数据
+				t_dispatch_command_info.m_car_number = tp_result->getString("car_number");
+				t_dispatch_command_info.m_primary_key = tp_result->getString("primary_key");
+				t_dispatch_command_info.m_unit = tp_result->getInt("unit");
+				t_dispatch_command_info.m_queue_id = tp_result->getInt("queue_id");
+				t_dispatch_command_info.m_type = tp_result->getInt("type");
+				t_dispatch_command_info.m_statu = tp_result->getInt("statu");
+				t_dispatch_command_info.m_space_info = tp_result->getString("space_info");
+				t_dispatch_command_info.m_measure_info = tp_result->getString("measure_info");
+//				t_dispatch_command_info.m_export_id = tp_result->getInt("export_id");
+				t_dispatch_command_info.m_export_id = 0;
+
+				//m_type指令类型, 0无效, 1存车, 2取车,
+				if ( t_dispatch_command_info.m_type == 1)
+				{
+					//存车, 数据库特有 雷达信息,  没有车位信息, 需要根据车高,再去车位表申请车位
+					if(! google::protobuf::TextFormat::ParseFromString(t_dispatch_command_info.m_measure_info, &t_dispatch_command_info.m_measure_info_msg))
+					{
+						return Error_manager(Error_code::ERROR, Error_level::MINOR_ERROR,
+											 "ParseFromString fun error, m_measure_info ");
+					}
+					t_dispatch_command_info.m_useless_distance = m_device_floor-1;
+				}
+				else if ( t_dispatch_command_info.m_type == 2 )
+				{
+					//取车, 数据库特有车位信息
+					if(! google::protobuf::TextFormat::ParseFromString(t_dispatch_command_info.m_space_info, &t_dispatch_command_info.m_parkspace_info_msg))
+					{
+						return Error_manager(Error_code::ERROR, Error_level::MINOR_ERROR,
+											 "ParseFromString fun error, m_space_info ");
+					}
+					t_dispatch_command_info.m_useless_distance = t_dispatch_command_info.m_parkspace_info_msg.floor()-m_device_floor;
+				}
+				else
+				{
+					return Error_manager(Error_code::ERROR, Error_level::MINOR_ERROR,
+										 "command_queue m_type error ");
+				}
+
+				if ( t_dispatch_command_info.m_useless_distance <0 )
+				{
+					t_dispatch_command_info.m_useless_distance = 0-t_dispatch_command_info.m_useless_distance;
+				}
+				m_dispatch_command_map[t_dispatch_command_info.m_car_number] = t_dispatch_command_info;
+			}
+			catch (sql::SQLException &e)
+			{
+				/* Use what() (derived from std::runtime_error) to fetch the error message */
+				sprintf(t_error_buf, "# ERR: %s\n (MySQL error code: %d, SQLState: %s", e.what(), e.getErrorCode(),
+						e.getSQLState().c_str());
+				return Error_manager(DB_RESULT_SET_PARSE_ERROR, NEGLIGIBLE_ERROR, t_error_buf);
+			}
+			catch (std::runtime_error &e)
+			{
+				sprintf(t_error_buf, "# ERR: %s\n ERR: runtime_error in  %s ", e.what(), __FILE__);
+				return Error_manager(DB_RESULT_SET_PARSE_ERROR, NEGLIGIBLE_ERROR, t_error_buf);
+			}
+		}
+		return SUCCESS;
+	}
+	else
+	{
+		return t_error;
+	}
+	return Error_code::SUCCESS;
+}
+
+//对调度指令进行排序, 选出最优解, 比较存车和取车
+Error_manager Dispatch_command::sort_dispatch_command_for_total()
+{
+	int t_optimal_loss=0x7fffffff;		//最优loss值
+	m_car_number_optimal.clear();
+	for (auto iter = m_dispatch_command_map.begin(); iter != m_dispatch_command_map.end(); ++iter)
+	{
+		//loss = 空跑路程 + 排队编号, 求最小值
+		int t_current_loss = iter->second.m_useless_distance + iter->second.m_queue_id;
+		if ( t_optimal_loss > t_current_loss )
+		{
+			t_optimal_loss = t_current_loss;
+			m_car_number_optimal = iter->first;
+		}
+	}
+	if ( m_car_number_optimal.empty() )
+	{
+		return Error_code::NODATA;
+	}
+	return Error_code::SUCCESS;
+}
+
+
+//对调度指令进行排序, 选出最优解, 只比较存车
+Error_manager Dispatch_command::sort_dispatch_command_for_park()
+{
+	int t_optimal_loss=0x7fffffff;		//最优loss值
+	m_car_number_optimal.clear();
+	for (auto iter = m_dispatch_command_map.begin(); iter != m_dispatch_command_map.end(); ++iter)
+	{
+		//loss = 空跑路程 + 排队编号, 求最小值
+		int t_current_loss = iter->second.m_useless_distance + iter->second.m_queue_id;
+		if ( t_optimal_loss > t_current_loss && iter->second.m_type == 1)
+		{
+			t_optimal_loss = t_current_loss;
+			m_car_number_optimal = iter->first;
+		}
+	}
+	if ( m_car_number_optimal.empty() )
+	{
+		return Error_code::NODATA;
+	}
+	return Error_code::SUCCESS;
+}
+
+//存车指令 获取 指定车高 指定单元 的车位信息,用于车位分配
+Error_manager Dispatch_command::query_specify_height_unit_parkspace_info(int unit, float height, Dispatch_space_info & dispatch_space_info)
+{
+	//查询车位表
+	char query_parkspace_sql[1024];
+	memset(query_parkspace_sql, 0, 1024);
+	int t_statu = 0; //车位状态, 0可用, 1故障
+	sprintf(query_parkspace_sql,"select * from space where car_number is NULL and ABS(height- %f) < 1e-5 and statu = %d and unit = %d",height,t_statu,unit);
+	boost::shared_ptr<sql::ResultSet>  tp_result = nullptr;
+	Error_manager ec = Database_controller::get_instance_pointer()->sql_query(query_parkspace_sql, tp_result);
+	if(ec == SUCCESS)
+	{
+		if(tp_result == nullptr)
+		{
+			return DB_RESULT_SET_EMPTY;
+		}
+		//只取第一条结果, 默认是id最小的,
+		if (tp_result->next())
+		{
+			char buf[1024];
+			memset(buf, 0, 1024);
+			try
+			{
+				//解析数据
+				dispatch_space_info.m_id = tp_result->getInt("id");
+				dispatch_space_info.m_floor = tp_result->getInt("floor");
+				dispatch_space_info.m_subID = tp_result->getInt("subID");
+				dispatch_space_info.m_height = tp_result->getDouble("height");
+				dispatch_space_info.m_car_number = tp_result->getString("car_number");
+				dispatch_space_info.m_unit = tp_result->getInt("unit");
+				dispatch_space_info.m_statu = tp_result->getInt("statu");
+			}
+			catch (sql::SQLException &e)
+			{
+				/* Use what() (derived from std::runtime_error) to fetch the error message */
+				sprintf(buf, "# ERR: %s\n (MySQL error code: %d, SQLState: %s", e.what(), e.getErrorCode(), e.getSQLState().c_str());
+				return Error_manager(DB_RESULT_SET_PARSE_ERROR, NEGLIGIBLE_ERROR, buf);
+			}
+			catch (std::runtime_error &e)
+			{
+				sprintf(buf, "# ERR: %s\n ERR: runtime_error in  %s ", e.what(), __FILE__);
+				return Error_manager(DB_RESULT_SET_PARSE_ERROR, NEGLIGIBLE_ERROR, buf);
+			}
+		}
+		else
+		{
+			return Error_manager(Error_code::DB_NOT_QUERY_EMPTY_PARKSPACE, Error_level::MINOR_ERROR,
+								 "数据库未查询到空车位 Parkspace_operating_function::query_one_empty_parkspace error ");
+		}
+		return SUCCESS;
+	}
+	else
+	{
+		return ec;
+	}
+	return SUCCESS;
+}
+
+//查询空闲车位最优解,    存车指令 根据调度指令最优解 获取 空闲车位最优解
+Error_manager Dispatch_command::query_dispatch_space_optimal()
+{
+	Error_manager t_error;
+
+	int t_unit = m_dispatch_command_map[m_car_number_optimal].m_unit;
+	float t_height = m_dispatch_command_map[m_car_number_optimal].m_measure_info_msg.height();
+
+	//小车对应小车位  中车对应中车位 大车对应大车位
+	if ( 0 < t_height && t_height <= CAR_HEIGHT_LIMIT_SMALL )
+	{
+		t_error = query_specify_height_unit_parkspace_info(t_unit, CAR_HEIGHT_LIMIT_SMALL, m_dispatch_space_info);
+		if ( t_error == Error_code::SUCCESS )
+		{
+			m_car_type = Common_data::Car_type::MIN_CAR;
+			return t_error;
+		}
+	}
+	if (  t_height <= CAR_HEIGHT_LIMIT_MIDDLE )
+	{
+		t_error = query_specify_height_unit_parkspace_info(t_unit, CAR_HEIGHT_LIMIT_MIDDLE, m_dispatch_space_info);
+		if ( t_error == Error_code::SUCCESS )
+		{
+			m_car_type = Common_data::Car_type::MID_CAR;
+			return t_error;
+		}
+	}
+	if ( t_height <= CAR_HEIGHT_LIMIT_BIG )
+	{
+		t_error = query_specify_height_unit_parkspace_info(t_unit, CAR_HEIGHT_LIMIT_BIG, m_dispatch_space_info);
+		if ( t_error == Error_code::SUCCESS )
+		{
+			m_car_type = Common_data::Car_type::BIG_CAR;
+			return t_error;
+		}
+	}
+	return Error_manager(Error_code::DB_NOT_QUERY_EMPTY_PARKSPACE, Error_level::MINOR_ERROR,
+						 " query_dispatch_space_optimal error ");
+}
+
+//查询空闲车位最优解,    存车指令 根据调度指令最优解 获取 空闲车位最优解
+Error_manager Dispatch_command::query_dispatch_space_optimal(Common_data::Car_type reallocate_car_type)
+{
+	Error_manager t_error;
+
+	int t_unit = m_dispatch_command_map[m_car_number_optimal].m_unit;
+//	float t_height = m_dispatch_command_map[m_car_number_optimal].m_measure_info_msg.height();
+
+	//小车对应小车位  中车对应中车位 大车对应大车位
+	if ( reallocate_car_type == Common_data::Car_type::MIN_CAR )
+	{
+		t_error = query_specify_height_unit_parkspace_info(t_unit, CAR_HEIGHT_LIMIT_SMALL, m_dispatch_space_info);
+		if ( t_error == Error_code::SUCCESS )
+		{
+			m_car_type = Common_data::Car_type::MIN_CAR;
+			return t_error;
+		}
+	}
+	if ( reallocate_car_type == Common_data::Car_type::MIN_CAR ||
+		 reallocate_car_type == Common_data::Car_type::MID_CAR )
+	{
+		t_error = query_specify_height_unit_parkspace_info(t_unit, CAR_HEIGHT_LIMIT_MIDDLE, m_dispatch_space_info);
+		if ( t_error == Error_code::SUCCESS )
+		{
+			m_car_type = Common_data::Car_type::MID_CAR;
+			return t_error;
+		}
+	}
+	if ( reallocate_car_type == Common_data::Car_type::MIN_CAR ||
+		 reallocate_car_type == Common_data::Car_type::MID_CAR ||
+		 reallocate_car_type == Common_data::Car_type::BIG_CAR )
+	{
+		t_error = query_specify_height_unit_parkspace_info(t_unit, CAR_HEIGHT_LIMIT_BIG, m_dispatch_space_info);
+		if ( t_error == Error_code::SUCCESS )
+		{
+			m_car_type = Common_data::Car_type::BIG_CAR;
+			return t_error;
+		}
+	}
+	return Error_manager(Error_code::DB_NOT_QUERY_EMPTY_PARKSPACE, Error_level::MINOR_ERROR,
+						 " query_dispatch_space_optimal error ");
+}
+
+//查询 取车的车位    取车指令 根据车牌号 查询对应的车位
+Error_manager Dispatch_command::query_dispatch_space_for_car_number()
+{
+//查询车位表
+	char query_parkspace_sql[1024];
+	memset(query_parkspace_sql, 0, 1024);
+	int t_statu = 0; //车位状态, 0可用, 1故障
+	sprintf(query_parkspace_sql,"select * from space where car_number = '%s' ",m_dispatch_command_map[m_car_number_optimal].m_car_number.c_str());
+//	std::cout<<"query_parkspace_sql = "<<query_parkspace_sql<<std::endl;
+	boost::shared_ptr<sql::ResultSet>  tp_result = nullptr;
+	Error_manager ec = Database_controller::get_instance_pointer()->sql_query(query_parkspace_sql, tp_result);
+	if(ec == SUCCESS)
+	{
+		if(tp_result == nullptr)
+		{
+			return DB_RESULT_SET_EMPTY;
+		}
+		//只取第一条结果, 默认是id最小的,
+		if (tp_result->next())
+		{
+			char buf[1024];
+			memset(buf, 0, 1024);
+			try
+			{
+				//解析数据
+				m_dispatch_space_info.m_id = tp_result->getInt("id");
+				m_dispatch_space_info.m_floor = tp_result->getInt("floor");
+				m_dispatch_space_info.m_subID = tp_result->getInt("subID");
+				m_dispatch_space_info.m_height = tp_result->getDouble("height");
+				m_dispatch_space_info.m_car_number = tp_result->getString("car_number");
+				m_dispatch_space_info.m_unit = tp_result->getInt("unit");
+				m_dispatch_space_info.m_statu = tp_result->getInt("statu");
+			}
+			catch (sql::SQLException &e)
+			{
+				/* Use what() (derived from std::runtime_error) to fetch the error message */
+				sprintf(buf, "# ERR: %s\n (MySQL error code: %d, SQLState: %s", e.what(), e.getErrorCode(), e.getSQLState().c_str());
+				return Error_manager(DB_RESULT_SET_PARSE_ERROR, NEGLIGIBLE_ERROR, buf);
+			}
+			catch (std::runtime_error &e)
+			{
+				sprintf(buf, "# ERR: %s\n ERR: runtime_error in  %s ", e.what(), __FILE__);
+				return Error_manager(DB_RESULT_SET_PARSE_ERROR, NEGLIGIBLE_ERROR, buf);
+			}
+		}
+		else
+		{
+			return Error_manager(Error_code::DB_QUERY_NOT_DATA, Error_level::MINOR_ERROR,
+								 "数据库未查询到数据 Parkspace_operating_function::query_one_parkspace_with_license error ");
+
+		}
+		return SUCCESS;
+	}
+	else
+	{
+		return ec;
+	}
+	return SUCCESS;
+}
+
+//查询 取车的车辆感测信息    取车指令 根据key 查询感测信息
+Error_manager Dispatch_command::query_dispatch_vehicle_for_primary_key()
+{
+	//查询 车辆表
+	char query_parkspace_sql[1024];
+	memset(query_parkspace_sql, 0, 1024);
+	int t_statu = 0; //车位状态, 0可用, 1故障
+	sprintf(query_parkspace_sql,"select * from vehicle where primary_key = '%s' ",m_dispatch_command_map[m_car_number_optimal].m_primary_key.c_str());
+//	std::cout<<"query_parkspace_sql = "<<query_parkspace_sql<<std::endl;
+	boost::shared_ptr<sql::ResultSet>  tp_result = nullptr;
+	Error_manager ec = Database_controller::get_instance_pointer()->sql_query(query_parkspace_sql, tp_result);
+	if(ec == SUCCESS)
+	{
+		if(tp_result == nullptr)
+		{
+			return DB_RESULT_SET_EMPTY;
+		}
+		//只取第一条结果, 默认是id最小的,
+		if (tp_result->next())
+		{
+			char buf[1024];
+			memset(buf, 0, 1024);
+			try
+			{
+				//解析数据
+				m_dispatch_vehicle_info.m_car_number = tp_result->getString("car_number");
+				m_dispatch_vehicle_info.m_primary_key = tp_result->getString("primary_key");
+				m_dispatch_vehicle_info.m_actually_measure_info = tp_result->getString("actually_measure_info");
+
+				//取车, 数据库特有车位信息
+				if(! google::protobuf::TextFormat::ParseFromString(m_dispatch_vehicle_info.m_actually_measure_info, &m_dispatch_vehicle_info.m_actually_measure_info_msg))
+				{
+					return Error_manager(Error_code::ERROR, Error_level::MINOR_ERROR,
+										 "ParseFromString fun error, m_space_info ");
+				}
+			}
+			catch (sql::SQLException &e)
+			{
+				/* Use what() (derived from std::runtime_error) to fetch the error message */
+				sprintf(buf, "# ERR: %s\n (MySQL error code: %d, SQLState: %s", e.what(), e.getErrorCode(), e.getSQLState().c_str());
+				return Error_manager(DB_RESULT_SET_PARSE_ERROR, NEGLIGIBLE_ERROR, buf);
+			}
+			catch (std::runtime_error &e)
+			{
+				sprintf(buf, "# ERR: %s\n ERR: runtime_error in  %s ", e.what(), __FILE__);
+				return Error_manager(DB_RESULT_SET_PARSE_ERROR, NEGLIGIBLE_ERROR, buf);
+			}
+		}
+		else
+		{
+			return Error_manager(Error_code::DB_QUERY_NOT_DATA, Error_level::MINOR_ERROR,
+								 "数据库未查询到数据 Parkspace_operating_function::query_one_parkspace_with_license error ");
+
+		}
+		return SUCCESS;
+	}
+	else
+	{
+		return ec;
+	}
+	return SUCCESS;
+}
+
+
+//更新 车位状态, 根据车位ID 写入车牌号即可
+Error_manager Dispatch_command::update_parkspace_info_write_car_number()
+{
+	//执行sql操作
+	char update_space_sql[1024];
+	memset(update_space_sql, 0, 1024);
+	sprintf(update_space_sql, "update space set car_number = '%s' where id = %d",
+			m_dispatch_command_map[m_car_number_optimal].m_car_number.c_str(),
+			m_dispatch_command_map[m_car_number_optimal].m_parkspace_info_msg.id() );
+//			m_dispatch_space_info.m_id);
+	Error_manager ec = Database_controller::get_instance_pointer()->sql_update(update_space_sql);
+	return ec;
+}
+
+//更新 车位状态, 找到车牌号, 写NULL
+Error_manager Dispatch_command::update_parkspace_info_clear_car_number()
+{
+	//执行sql操作
+	char update_space_sql[1024];
+	memset(update_space_sql, 0, 1024);
+	sprintf(update_space_sql, "update space set car_number = null where car_number = '%s' ",
+			m_dispatch_command_map[m_car_number_optimal].m_car_number.c_str());
+	Error_manager ec = Database_controller::get_instance_pointer()->sql_update(update_space_sql);
+	return ec;
+}
+
+//更新 指令队列, 根据车牌号 修改状态即可,  //指令状态, 0排队中, 1正在工作, 2已完成, 3故障异常
+Error_manager Dispatch_command::update_command_queue_for_statu(int statu)
+{
+	char update_command_sql[1024];
+	memset(update_command_sql, 0, 1024);
+	sprintf(update_command_sql, "update command_queue set statu = %d, export_id = %d where car_number = '%s'",
+			statu, m_dispatch_command_map[m_car_number_optimal].m_export_id,
+			m_dispatch_command_map[m_car_number_optimal].m_car_number.c_str());
+	LOG(INFO) << "jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj update_command_sql =  "<< update_command_sql << " --- " << this;
+	Error_manager ec = Database_controller::get_instance_pointer()->sql_update(update_command_sql);
+	return ec;
+}
+
+//更新 指令队列, 根据车牌号 删除指令
+Error_manager Dispatch_command::delete_command_queue_for_statu()
+{
+	char delete_command_sql[1024];
+	memset(delete_command_sql, 0, 1024);
+	sprintf(delete_command_sql, "delete from command_queue where car_number = '%s'",
+			m_dispatch_command_map[m_car_number_optimal].m_car_number.c_str());
+	Error_manager ec = Database_controller::get_instance_pointer()->sql_delete(delete_command_sql);
+	return ec;
+}
+
+//制作存车表单
+Error_manager Dispatch_command::create_park_table()
+{
+	park_table t_park_table;
+	t_park_table.mutable_statu()->set_execute_statu(eNormal);
+	t_park_table.set_queue_id(m_dispatch_command_map[m_car_number_optimal].m_queue_id);
+	t_park_table.set_car_number(m_dispatch_command_map[m_car_number_optimal].m_car_number);
+	t_park_table.set_unit_id(m_dispatch_command_map[m_car_number_optimal].m_unit);
+	t_park_table.set_primary_key(m_dispatch_command_map[m_car_number_optimal].m_primary_key);
+	t_park_table.mutable_entrance_measure_info()->CopyFrom(m_dispatch_command_map[m_car_number_optimal].m_measure_info_msg);
+	t_park_table.mutable_allocated_space_info()->CopyFrom(m_dispatch_command_map[m_car_number_optimal].m_parkspace_info_msg);
+
+	//根据雷达x坐标, 计算入口id
+	int t_terminal = 0;
+	if (m_dispatch_command_map[m_car_number_optimal].m_measure_info_msg.cx()<0)
+	{
+		t_terminal = m_dispatch_id*2+1;
+	}
+	else if(m_dispatch_command_map[m_car_number_optimal].m_measure_info_msg.cx()>0)
+	{
+		t_terminal = m_dispatch_id*2+2;
+	}
+	t_park_table.set_terminal_id(t_terminal);
+//	std::cout << " huli test :::: " << " iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii m_park_table_msg.entrance_measure_info().cx() = " << m_park_table_msg.entrance_measure_info().cx() << std::endl;
+//	std::cout << " huli test :::: " << " iiiiiiiiiiiiiiiiiiiiiiiiiiiiii t_terminal = " << t_terminal << std::endl;
+	LOG(INFO) << " m_park_table_msg.entrance_measure_info().cx() =  "<< m_park_table_msg.entrance_measure_info().cx() << " --- " << this;
+	LOG(INFO) << " t_terminal =  "<< t_terminal << " --- " << this;
+	LOG(INFO) << " m_device_floor =  "<< m_device_floor << " --- " << this;
+	LOG(INFO) << " m_dispatch_id =  "<< m_dispatch_id << " --- " << this;
+	LOG(INFO) << " m_unit =  "<< m_unit << " --- " << this;
+	LOG(INFO) << " m_outlet_ready =  "<< m_outlet_ready << " --- " << this;
+
+	m_park_table_msg = t_park_table;
+	return Error_code::SUCCESS;
+}
+
+//制作取车表单
+Error_manager Dispatch_command::create_pick_table(int outlet_ready)
+{
+	pick_table t_pick_table;
+	t_pick_table.mutable_statu()->set_execute_statu(eNormal);
+	t_pick_table.set_queue_id(m_dispatch_command_map[m_car_number_optimal].m_queue_id);
+	t_pick_table.set_car_number(m_dispatch_command_map[m_car_number_optimal].m_car_number);
+	t_pick_table.set_unit_id(m_dispatch_command_map[m_car_number_optimal].m_unit);
+	t_pick_table.set_primary_key(m_dispatch_command_map[m_car_number_optimal].m_primary_key);
+	t_pick_table.mutable_actually_measure_info()->CopyFrom(m_dispatch_command_map[m_car_number_optimal].m_measure_info_msg);
+	t_pick_table.mutable_actually_space_info()->CopyFrom(m_dispatch_command_map[m_car_number_optimal].m_parkspace_info_msg);
+
+	t_pick_table.set_terminal_id(outlet_ready);
+
+	LOG(INFO) << " outlet_ready =  "<< outlet_ready << " --- " << this;
+
+	LOG(INFO) << " m_device_floor =  "<< m_device_floor << " --- " << this;
+	LOG(INFO) << " m_dispatch_id =  "<< m_dispatch_id << " --- " << this;
+	LOG(INFO) << " m_unit =  "<< m_unit << " --- " << this;
+	LOG(INFO) << " m_outlet_ready =  "<< m_outlet_ready << " --- " << this;
+
+
+	m_pick_table_msg = t_pick_table;
+	return Error_code::SUCCESS;
+}
+
+//增加 车辆表, 存车指令 完成后添加车辆信息
+Error_manager Dispatch_command::insert_vehicle_for_car_number()
+{
+	char insert_vehicle_sql[1024];
+	memset(insert_vehicle_sql, 0, 1024);
+	sprintf(insert_vehicle_sql, "INSERT INTO vehicle (car_number,primary_key,actually_measure_info) values ('%s','%s','%s')",
+			m_car_number_optimal.c_str(), m_dispatch_command_map[m_car_number_optimal].m_primary_key.c_str(),
+			m_dispatch_command_map[m_car_number_optimal].m_measure_info.c_str()   );
+	Error_manager ec = Database_controller::get_instance_pointer()->sql_insert(insert_vehicle_sql);
+	return ec;
+}
+//删除 车辆表, 取车指令 完成后删除车辆信息
+Error_manager Dispatch_command::delete_vehicle_for_car_number()
+{
+	char delete_vehicle_sql[1024];
+	memset(delete_vehicle_sql, 0, 1024);
+	sprintf(delete_vehicle_sql, "delete from vehicle where car_number = '%s'",
+			m_dispatch_command_map[m_car_number_optimal].m_car_number.c_str());
+	Error_manager ec = Database_controller::get_instance_pointer()->sql_delete(delete_vehicle_sql);
+	return ec;
+}
+
+
+
+
+

+ 175 - 0
plc调度节点/dispatch/dispatch_command.h

@@ -0,0 +1,175 @@
+
+#ifndef __DISPATCH_COMMAND_HH__
+#define __DISPATCH_COMMAND_HH__
+
+#include "../tool/singleton.h"
+#include "../tool/thread_condition.h"
+#include "../error_code/error_code.h"
+#include "../dispatch/database_controller.h"
+#include "../message/message.pb.h"
+#include "../tool/common_data.h"
+#include <string>
+#include <map>
+#include <glog/logging.h>
+
+
+
+//调度指令模块, 主要是与数据库的表 command_queue 同步, 然后按照一定的策略
+class Dispatch_command
+{
+public:
+
+
+
+
+	//调度指令模块 的状态
+	enum Dispatch_command_status
+	{
+		E_DISPATCH_COMMAND_UNKNOW               = 0,    //未知
+		E_DISPATCH_COMMAND_READY                = 1,    //准备,待机
+
+		E_DISPATCH_COMMAND_BUSY					= 2, 	//工作正忙
+		E_DISPATCH_COMMAND_DISCONNECT			= 3, 	//断连
+
+		E_DISPATCH_COMMAND_FAULT               	= 100,  //故障
+	};
+
+	//调度指令, 格式和数据库的 command_queue 保持一致
+	struct Dispatch_command_info
+	{
+	    std::string							m_car_number;			//车牌号
+	    std::string							m_primary_key;			//唯一码
+	    int 								m_unit;					//单元号, 1~3
+	    int 								m_queue_id;				//排序的id, 从0开始递增
+	    int 								m_type;					//指令类型, 0无效, 1存车, 2取车,
+	    int									m_statu;				//指令状态, 0排队中, 1正在工作, 2已完成, 3故障异常
+	    std::string							m_space_info;			//车位信息的DebugString, 默认没有, 存车要根据感测信息的车高去申请车位, 取车根据车牌号找车位
+		parkspace_info						m_parkspace_info_msg;	//车位信息的proto格式
+		std::string							m_measure_info;			//感测信息的DebugString, 里面自带车高, 小1.5  中1.7  大1.9,
+		measure_info						m_measure_info_msg;		//感测信息的proto格式
+	    int 								m_export_id;			//出入口id, 1~6
+
+	    int 								m_useless_distance;		//空跑的路程,
+
+	};
+
+	//调度车位信息, 格式和数据库的 space 保持一致
+	struct Dispatch_space_info
+	{
+	    int 								m_id;					//车位id
+	    int 								m_floor;				//车位楼层
+	    int 								m_subID;				//层内id
+	    float 								m_height;				//车位高度, 小1.55  中1.75  大2.2,
+		std::string							m_car_number;			//车牌号
+		int 								m_unit;					//单元号, 1~3
+		int									m_statu;				//车位状态, 0可用, 1故障
+	};
+
+	//调度车辆信息, 格式和数据库的 vehicle 保持一致
+	struct Dispatch_vehicle_info
+	{
+		std::string							m_car_number;			//车牌号
+		std::string							m_primary_key;			//唯一码
+		std::string							m_actually_measure_info;			//感测信息的DebugString, 里面自带车高, 小1.5  中1.7  大1.9,
+		measure_info						m_actually_measure_info_msg;		//感测信息的proto格式
+	};
+
+public:
+	Dispatch_command();
+	Dispatch_command(const Dispatch_command& other)= default;
+	Dispatch_command& operator =(const Dispatch_command& other)= default;
+	~Dispatch_command();
+public://API functions
+
+
+	//调度开始前, 向数据库发送请求的相关操作, 输入 穿梭机所在的楼层, 调度id 0~2, 空闲出口id, 如果不是0,就表示有空闲的出口
+	Error_manager dispatch_request_to_sql(int plc_floor, int dispatch_id, int outlet_ready);
+
+	//调度完成后, 向数据库发送答复的相关操作
+	Error_manager dispatch_response_to_sql(Error_manager error);
+
+	//调度 , 向数据库 重新分配车位,
+	Error_manager dispatch_reallocate_to_sql(Common_data::Car_type reallocate_car_type, int outlet_ready);
+
+	//检查出口是否空闲, 检查指令队列的取车完成的出口id是否存在, 不存在就是空闲,返回成功
+	Error_manager check_export_id_is_ready(int export_id);
+
+public://get or set member variable
+
+protected://member functions
+
+	//获取调度指令, 与数据库同步 command_queue
+	Error_manager query_all_dispatch_command();
+
+	//对调度指令进行排序, 选出最优解, 比较存车和取车
+	Error_manager sort_dispatch_command_for_total();
+
+	//对调度指令进行排序, 选出最优解, 只比较存车
+	Error_manager sort_dispatch_command_for_park();
+
+	//获取 指定车高 指定单元 的车位信息,用于车位分配, 找不到就会报错,
+	Error_manager query_specify_height_unit_parkspace_info(int unit, float height, Dispatch_space_info & dispatch_space_info);
+
+	//查询空闲车位最优解,    存车指令 根据调度指令最优解 获取 空闲车位最优解
+	Error_manager query_dispatch_space_optimal();
+	//查询空闲车位最优解,    存车指令 根据调度指令最优解 获取 空闲车位最优解
+	Error_manager query_dispatch_space_optimal(Common_data::Car_type reallocate_car_type);
+
+	//查询 取车的车位    取车指令 根据车牌号 查询对应的车位
+	Error_manager query_dispatch_space_for_car_number();
+	//查询 取车的车辆感测信息    取车指令 根据key 查询感测信息
+	Error_manager query_dispatch_vehicle_for_primary_key();
+
+	//更新 车位状态, 根据车位ID 修改车牌号即可,
+	Error_manager update_parkspace_info_write_car_number();
+	//更新 车位状态, 找到车牌号, 写NULL
+	Error_manager update_parkspace_info_clear_car_number();
+
+	//更新 指令队列, 根据车牌号 修改状态即可,  //指令状态, 0排队中, 1正在工作, 2已完成, 3故障异常
+	Error_manager update_command_queue_for_statu(int statu);
+	//更新 指令队列, 根据车牌号 修改状态即可,  //指令状态, 0排队中, 1正在工作, 2已完成, 3故障异常
+//	Error_manager update_command_queue_for_statu(int statu, std::string error_description);
+
+	//更新 指令队列, 根据车牌号 删除指令
+	Error_manager delete_command_queue_for_statu();
+
+	//制作存车表单
+	Error_manager create_park_table();
+	//制作取车表单
+	Error_manager create_pick_table(int outlet_ready);
+
+	//增加 车辆表, 存车指令 完成后添加车辆信息
+	Error_manager insert_vehicle_for_car_number();
+	//删除 车辆表, 取车指令 完成后删除车辆信息
+	Error_manager delete_vehicle_for_car_number();
+
+
+
+protected://member variable
+public:
+	Dispatch_command_status							m_dispatch_command_status;			//调度指令模块 的状态
+	std::mutex                              		m_lock;        						// 锁.
+
+	int												m_dispatch_id;						//调度id, 0-2
+	int 											m_unit;								//单元号
+	int 											m_device_floor;						//穿梭机所在的楼层, 存车完在对应的车位楼层, 取车完在1楼
+	int 											m_outlet_ready;						//取车空闲出口id, 0表示没有出口, 1~6表示空闲出口
+
+	std::map<std::string, Dispatch_command_info>	m_dispatch_command_map;				//调度指令map, 数据库的所有信息
+	std::string										m_car_number_optimal;				//调度指令最优解
+	Dispatch_space_info								m_dispatch_space_info;				//调度车位最优解
+	Dispatch_vehicle_info							m_dispatch_vehicle_info;			//调度车位最优解
+
+	Common_data::Dispatch_process_type			m_dispatch_process_type ;			//调度流程类型
+	park_table									m_park_table_msg;					//停车表单
+	pick_table									m_pick_table_msg;					//取车表单
+	Common_data::Car_type						m_car_type;							//车的大小
+
+
+private:
+
+};
+
+
+#endif // __DISPATCH_COMMAND_HH__
+

+ 558 - 0
plc调度节点/dispatch/dispatch_communication.cpp

@@ -0,0 +1,558 @@
+//
+// Created by huli on 2020/9/25.
+//
+
+#include "dispatch_communication.h"
+
+
+Dispatch_communication::Dispatch_communication()
+{
+
+}
+
+
+Dispatch_communication::~Dispatch_communication()
+{
+
+}
+
+
+//初始化 通信 模块。如下三选一
+Error_manager Dispatch_communication::communication_init(int plc_id)
+{
+	m_plc_id = plc_id;
+
+
+	int t_index = 0;
+	std::vector<Snap7_buf::Variable_information>		t_variable_information_vector;
+
+	//往map通信缓存里面添加所需要的buf
+	std::unique_lock<std::mutex> t_lock1(m_receive_buf_lock);
+	std::unique_lock<std::mutex> t_lock2(m_send_buf_lock);
+	Snap7_buf t_snap7_buf;
+
+
+
+//调度指令
+	t_index = 0;
+	t_variable_information_vector.clear();
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_request_status", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 1 });
+	t_index += sizeof(unsigned char)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_reserved51", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 1 });
+	t_index += sizeof(unsigned char)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_working_total_time", typeid(float).name(), t_index,sizeof(float), 1 });
+	t_index += sizeof(float)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_working_remaining_time", typeid(float).name(), t_index,sizeof(float), 1 });
+	t_index += sizeof(float)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_reserved60_73", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 14 });
+	t_index += sizeof(unsigned char)*14;
+
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_request_dispatch_motion_direction", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 1 });
+	t_index += sizeof(unsigned char)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_reserved75_79", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 5 });
+	t_index += sizeof(unsigned char)*5;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_request_passageway_id", typeid(unsigned int).name(), t_index,sizeof(unsigned int), 1 });
+	t_index += sizeof(unsigned int)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_request_passageway_direction", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 1 });
+	t_index += sizeof(unsigned char)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_reserved85_89", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 5 });
+	t_index += sizeof(unsigned char)*5;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_request_parkingspace_index_id", typeid(unsigned int).name(), t_index,sizeof(unsigned int), 1 });
+	t_index += sizeof(unsigned int)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_request_parkingspace_unit_id", typeid(unsigned int).name(), t_index,sizeof(unsigned int), 1 });
+	t_index += sizeof(unsigned int)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_request_parkingspace_label_id", typeid(unsigned int).name(), t_index,sizeof(unsigned int), 1 });
+	t_index += sizeof(unsigned int)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_request_parkingspace_floor_id", typeid(unsigned int).name(), t_index,sizeof(unsigned int), 1 });
+	t_index += sizeof(unsigned int)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_request_parkingspace_room_id", typeid(unsigned int).name(), t_index,sizeof(unsigned int), 1 });
+	t_index += sizeof(unsigned int)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_request_parkingspace_direction", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 1 });
+	t_index += sizeof(unsigned char)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_reserved111", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 1 });
+	t_index += sizeof(unsigned char)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_request_car_center_x", typeid(float).name(), t_index,sizeof(float), 1 });
+	t_index += sizeof(float)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_request_car_center_y", typeid(float).name(), t_index,sizeof(float), 1 });
+	t_index += sizeof(float)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_request_car_angle", typeid(float).name(), t_index,sizeof(float), 1 });
+	t_index += sizeof(float)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_request_car_front_theta", typeid(float).name(), t_index,sizeof(float), 1 });
+	t_index += sizeof(float)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_request_car_length", typeid(float).name(), t_index,sizeof(float), 1 });
+	t_index += sizeof(float)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_request_car_width", typeid(float).name(), t_index,sizeof(float), 1 });
+	t_index += sizeof(float)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_request_car_height", typeid(float).name(), t_index,sizeof(float), 1 });
+	t_index += sizeof(float)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_request_car_wheel_base", typeid(float).name(), t_index,sizeof(float), 1 });
+	t_index += sizeof(float)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_request_car_wheel_width", typeid(float).name(), t_index,sizeof(float), 1 });
+	t_index += sizeof(float)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_request_car_license", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 20 });
+	t_index += sizeof(unsigned char)*20;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_reserved168_187", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 20 });
+	t_index += sizeof(unsigned char)*20;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_request_car_type", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 1 });
+	t_index += sizeof(unsigned char)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_reserved189_191", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 3 });
+	t_index += sizeof(unsigned char)*3;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_request_uniformed_car_x", typeid(float).name(), t_index,sizeof(float), 1 });
+	t_index += sizeof(float)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_request_uniformed_car_y", typeid(float).name(), t_index,sizeof(float), 1 });
+	t_index += sizeof(float)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_reserved200_209", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 10 });
+	t_index += sizeof(unsigned char)*10;
+
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_request_anticollision_lidar_flag", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 1 });
+	t_index += sizeof(unsigned char)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_reserved211_215", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 5 });
+	t_index += sizeof(unsigned char)*5;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_request_car_wheel_base_exact_value", typeid(float).name(), t_index,sizeof(float), 1 });
+	t_index += sizeof(float)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_reserved217_231", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 25 });
+	t_index += sizeof(unsigned char)*25;
+
+//	t_snap7_buf.init(DISPATCH_REQUEST_FROM_MANAGER_TO_PLC_DBNUMBER_0 +m_plc_id*100, 50, sizeof(Dispatch_request_from_manager_to_plc_for_data), t_variable_information_vector, Snap7_buf::LOOP_COMMUNICATION);
+	t_snap7_buf.init(DISPATCH_REQUEST_FROM_MANAGER_TO_PLC_DBNUMBER_0 , 50, sizeof(Dispatch_request_from_manager_to_plc_for_data), t_variable_information_vector, Snap7_buf::LOOP_COMMUNICATION);
+	m_send_buf_map[0] = t_snap7_buf;
+
+
+
+	t_index = 0;
+	t_variable_information_vector.clear();
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_request_key", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 50 });
+	t_index += sizeof(unsigned char)*50;
+
+//	t_snap7_buf.init(DISPATCH_REQUEST_FROM_MANAGER_TO_PLC_DBNUMBER_0 +m_plc_id*100, 0, sizeof(Dispatch_request_from_manager_to_plc_for_key), t_variable_information_vector, Snap7_buf::LOOP_COMMUNICATION);
+	t_snap7_buf.init(DISPATCH_REQUEST_FROM_MANAGER_TO_PLC_DBNUMBER_0 , 0, sizeof(Dispatch_request_from_manager_to_plc_for_key), t_variable_information_vector, Snap7_buf::LOOP_COMMUNICATION);
+	m_send_buf_map[1] = t_snap7_buf;
+
+
+
+	t_index = 0;
+	t_variable_information_vector.clear();
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_response_key", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 50 });
+	t_index += sizeof(unsigned char)*50;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_reserved50", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 1 });
+	t_index += sizeof(unsigned char)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_reserved51", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 1 });
+	t_index += sizeof(unsigned char)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_working_total_time", typeid(float).name(), t_index,sizeof(float), 1 });
+	t_index += sizeof(float)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_working_remaining_time", typeid(float).name(), t_index,sizeof(float), 1 });
+	t_index += sizeof(float)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_reserved60_73", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 14 });
+	t_index += sizeof(unsigned char)*14;
+
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_request_dispatch_motion_direction", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 1 });
+	t_index += sizeof(unsigned char)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_reserved75_79", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 5 });
+	t_index += sizeof(unsigned char)*5;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_request_passageway_id", typeid(unsigned int).name(), t_index,sizeof(unsigned int), 1 });
+	t_index += sizeof(unsigned int)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_request_passageway_direction", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 1 });
+	t_index += sizeof(unsigned char)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_reserved85_89", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 5 });
+	t_index += sizeof(unsigned char)*5;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_request_parkingspace_index_id", typeid(unsigned int).name(), t_index,sizeof(unsigned int), 1 });
+	t_index += sizeof(unsigned int)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_request_parkingspace_unit_id", typeid(unsigned int).name(), t_index,sizeof(unsigned int), 1 });
+	t_index += sizeof(unsigned int)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_request_parkingspace_label_id", typeid(unsigned int).name(), t_index,sizeof(unsigned int), 1 });
+	t_index += sizeof(unsigned int)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_request_parkingspace_floor_id", typeid(unsigned int).name(), t_index,sizeof(unsigned int), 1 });
+	t_index += sizeof(unsigned int)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_request_parkingspace_room_id", typeid(unsigned int).name(), t_index,sizeof(unsigned int), 1 });
+	t_index += sizeof(unsigned int)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_request_parkingspace_direction", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 1 });
+	t_index += sizeof(unsigned char)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_reserved111", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 1 });
+	t_index += sizeof(unsigned char)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_request_car_center_x", typeid(float).name(), t_index,sizeof(float), 1 });
+	t_index += sizeof(float)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_request_car_center_y", typeid(float).name(), t_index,sizeof(float), 1 });
+	t_index += sizeof(float)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_request_car_angle", typeid(float).name(), t_index,sizeof(float), 1 });
+	t_index += sizeof(float)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_request_car_front_theta", typeid(float).name(), t_index,sizeof(float), 1 });
+	t_index += sizeof(float)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_request_car_length", typeid(float).name(), t_index,sizeof(float), 1 });
+	t_index += sizeof(float)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_request_car_width", typeid(float).name(), t_index,sizeof(float), 1 });
+	t_index += sizeof(float)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_request_car_height", typeid(float).name(), t_index,sizeof(float), 1 });
+	t_index += sizeof(float)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_request_car_wheel_base", typeid(float).name(), t_index,sizeof(float), 1 });
+	t_index += sizeof(float)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_request_car_wheel_width", typeid(float).name(), t_index,sizeof(float), 1 });
+	t_index += sizeof(float)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_request_car_license", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 20 });
+	t_index += sizeof(unsigned char)*20;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_reserved168_187", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 20 });
+	t_index += sizeof(unsigned char)*20;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_request_car_type", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 1 });
+	t_index += sizeof(unsigned char)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_reserved189_191", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 3 });
+	t_index += sizeof(unsigned char)*3;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_request_uniformed_car_x", typeid(float).name(), t_index,sizeof(float), 1 });
+	t_index += sizeof(float)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_request_uniformed_car_y", typeid(float).name(), t_index,sizeof(float), 1 });
+	t_index += sizeof(float)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_reserved200_209", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 10 });
+	t_index += sizeof(unsigned char)*10;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_request_anticollision_lidar_flag", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 1 });
+	t_index += sizeof(unsigned char)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_reserved211_215", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 5 });
+	t_index += sizeof(unsigned char)*5;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_request_car_wheel_base_exact_value", typeid(float).name(), t_index,sizeof(float), 1 });
+	t_index += sizeof(float)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_reserved217_231", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 25 });
+	t_index += sizeof(unsigned char)*25;
+
+//	t_snap7_buf.init(DISPATCH_RESPONSE_FROM_PLC_TO_MANAGER_DBNUMBER_0 +m_plc_id*100, 0, sizeof(Dispatch_response_from_plc_to_manager), t_variable_information_vector, Snap7_buf::LOOP_COMMUNICATION);
+	t_snap7_buf.init(DISPATCH_RESPONSE_FROM_PLC_TO_MANAGER_DBNUMBER_0 , 0, sizeof(Dispatch_response_from_plc_to_manager), t_variable_information_vector, Snap7_buf::LOOP_COMMUNICATION);
+	m_receive_buf_map[0] = t_snap7_buf;
+
+
+	//调度状态
+	t_index = 0;
+	t_variable_information_vector.clear();
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_dispatch_heartbeat", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 1 });
+	t_index += sizeof(unsigned char)*1;
+
+//	t_snap7_buf.init(DISPATCH_PLC_STATUS_FROM_MANAGER_TO_PLC_DBNUMBER_0 +m_plc_id*100, 0, sizeof(Dispatch_plc_status_from_manager_to_plc), t_variable_information_vector, Snap7_buf::LOOP_COMMUNICATION);
+	t_snap7_buf.init(DISPATCH_PLC_STATUS_FROM_MANAGER_TO_PLC_DBNUMBER_0 , 0, sizeof(Dispatch_plc_status_from_manager_to_plc), t_variable_information_vector, Snap7_buf::LOOP_COMMUNICATION);
+	m_send_buf_map[2] = t_snap7_buf;
+
+	t_index = 0;
+	t_variable_information_vector.clear();
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_plc_heartbeat", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 1 });
+	t_index += sizeof(unsigned char)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_plc_status_info", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 1 });
+	t_index += sizeof(unsigned char)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_reserved2_37", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 36 });
+	t_index += sizeof(unsigned char)*36;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_turnplate_angle_min1", typeid(float).name(), t_index,sizeof(float), 1 });
+	t_index += sizeof(float)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_turnplate_angle_max1", typeid(float).name(), t_index,sizeof(float), 1 });
+	t_index += sizeof(float)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_turnplate_angle_min2", typeid(float).name(), t_index,sizeof(float), 1 });
+	t_index += sizeof(float)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_turnplate_angle_max2", typeid(float).name(), t_index,sizeof(float), 1 });
+	t_index += sizeof(float)*1;
+
+//	t_snap7_buf.init(DISPATCH_PLC_STATUS_FROM_PLC_TO_MANAGER_DBNUMBER_0 +m_plc_id*100, 0, sizeof(Dispatch_plc_status_from_plc_to_manager), t_variable_information_vector, Snap7_buf::NO_COMMUNICATION);
+	t_snap7_buf.init(DISPATCH_PLC_STATUS_FROM_PLC_TO_MANAGER_DBNUMBER_0 , 0, sizeof(Dispatch_plc_status_from_plc_to_manager), t_variable_information_vector, Snap7_buf::LOOP_COMMUNICATION);
+	m_receive_buf_map[1] = t_snap7_buf;
+
+
+
+	//地面雷达指令
+	t_index = 0;
+	t_variable_information_vector.clear();
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_request_car_center_x", typeid(float).name(), t_index,sizeof(float), 1 });
+	t_index += sizeof(float)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_request_car_center_y", typeid(float).name(), t_index,sizeof(float), 1 });
+	t_index += sizeof(float)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_request_car_angle", typeid(float).name(), t_index,sizeof(float), 1 });
+	t_index += sizeof(float)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_request_car_front_theta", typeid(float).name(), t_index,sizeof(float), 1 });
+	t_index += sizeof(float)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_request_car_length", typeid(float).name(), t_index,sizeof(float), 1 });
+	t_index += sizeof(float)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_request_car_width", typeid(float).name(), t_index,sizeof(float), 1 });
+	t_index += sizeof(float)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_request_car_height", typeid(float).name(), t_index,sizeof(float), 1 });
+	t_index += sizeof(float)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_request_car_wheel_base", typeid(float).name(), t_index,sizeof(float), 1 });
+	t_index += sizeof(float)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_request_car_wheel_width", typeid(float).name(), t_index,sizeof(float), 1 });
+	t_index += sizeof(float)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_request_uniformed_car_x", typeid(float).name(), t_index,sizeof(float), 1 });
+	t_index += sizeof(float)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_request_uniformed_car_y", typeid(float).name(), t_index,sizeof(float), 1 });
+	t_index += sizeof(float)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_response_locate_correct", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 1 });
+	t_index += sizeof(unsigned char)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_reserved45_48", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 3 });
+	t_index += sizeof(unsigned char)*3;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_heartbeat", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 1 });
+	t_index += sizeof(unsigned char)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_communication_mode", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 1 });
+	t_index += sizeof(unsigned char)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_refresh_command", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 1 });
+	t_index += sizeof(unsigned char)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_data_validity", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 1 });
+	t_index += sizeof(unsigned char)*1;
+
+
+
+//	t_snap7_buf.init(GROUND_LIDAR_RESPONSE_FROM_MANAGER_TO_PLC_DBNUMBER_0 +m_plc_id*100, 0, sizeof(Ground_lidar_response_from_manager_to_plc_for_data), t_variable_information_vector, Snap7_buf::LOOP_COMMUNICATION);
+	t_snap7_buf.init(GROUND_LIDAR_RESPONSE_FROM_MANAGER_TO_PLC_DBNUMBER_0 , 0, sizeof(Ground_lidar_response_from_manager_to_plc_for_data), t_variable_information_vector, Snap7_buf::LOOP_COMMUNICATION);
+	m_send_buf_map[3] = t_snap7_buf;
+//	t_snap7_buf.init(GROUND_LIDAR_RESPONSE_FROM_MANAGER_TO_PLC_DBNUMBER_1 +m_plc_id*100, 0, sizeof(Ground_lidar_response_from_manager_to_plc_for_data), t_variable_information_vector, Snap7_buf::LOOP_COMMUNICATION);
+	t_snap7_buf.init(GROUND_LIDAR_RESPONSE_FROM_MANAGER_TO_PLC_DBNUMBER_1 , 0, sizeof(Ground_lidar_response_from_manager_to_plc_for_data), t_variable_information_vector, Snap7_buf::LOOP_COMMUNICATION);
+	m_send_buf_map[4] = t_snap7_buf;
+
+
+	t_index = 0;
+	t_variable_information_vector.clear();
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_heartbeat", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 1 });
+	t_index += sizeof(unsigned char)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_communication_mode", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 1 });
+	t_index += sizeof(unsigned char)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_refresh_command", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 1 });
+	t_index += sizeof(unsigned char)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_data_validity", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 1 });
+	t_index += sizeof(unsigned char)*1;
+
+//	t_snap7_buf.init(GROUND_LIDAR_RESPONSE_FROM_MANAGER_TO_PLC_DBNUMBER_0 +m_plc_id*100, 0, sizeof(Ground_lidar_response_from_manager_to_plc_for_key), t_variable_information_vector, Snap7_buf::NO_COMMUNICATION);
+	t_snap7_buf.init(GROUND_LIDAR_RESPONSE_FROM_MANAGER_TO_PLC_DBNUMBER_0 , 0, sizeof(Ground_lidar_response_from_manager_to_plc_for_key), t_variable_information_vector, Snap7_buf::NO_COMMUNICATION);
+	m_send_buf_map[5] = t_snap7_buf;
+//	t_snap7_buf.init(GROUND_LIDAR_RESPONSE_FROM_MANAGER_TO_PLC_DBNUMBER_1 +m_plc_id*100, 0, sizeof(Ground_lidar_response_from_manager_to_plc_for_key), t_variable_information_vector, Snap7_buf::NO_COMMUNICATION);
+	t_snap7_buf.init(GROUND_LIDAR_RESPONSE_FROM_MANAGER_TO_PLC_DBNUMBER_1 , 0, sizeof(Ground_lidar_response_from_manager_to_plc_for_key), t_variable_information_vector, Snap7_buf::NO_COMMUNICATION);
+	m_send_buf_map[6] = t_snap7_buf;
+
+	t_index = 0;
+	t_variable_information_vector.clear();
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_heartbeat", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 1 });
+	t_index += sizeof(unsigned char)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_communication_mode", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 1 });
+	t_index += sizeof(unsigned char)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_refresh_command", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 1 });
+	t_index += sizeof(unsigned char)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_data_validity", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 1 });
+	t_index += sizeof(unsigned char)*1;
+
+//	t_snap7_buf.init(GROUND_LIDAR_REQUEST_FROM_PLC_TO_MANAGER_DBNUMBER_0 +m_plc_id*100, 0, sizeof(Ground_lidar_request_from_plc_to_manager), t_variable_information_vector, Snap7_buf::NO_COMMUNICATION);
+	t_snap7_buf.init(GROUND_LIDAR_REQUEST_FROM_PLC_TO_MANAGER_DBNUMBER_0 , 0, sizeof(Ground_lidar_request_from_plc_to_manager), t_variable_information_vector, Snap7_buf::NO_COMMUNICATION);
+	m_receive_buf_map[2] = t_snap7_buf;
+//	t_snap7_buf.init(GROUND_LIDAR_REQUEST_FROM_PLC_TO_MANAGER_DBNUMBER_1 +m_plc_id*100, 0, sizeof(Ground_lidar_request_from_plc_to_manager), t_variable_information_vector, Snap7_buf::NO_COMMUNICATION);
+	t_snap7_buf.init(GROUND_LIDAR_REQUEST_FROM_PLC_TO_MANAGER_DBNUMBER_1 , 0, sizeof(Ground_lidar_request_from_plc_to_manager), t_variable_information_vector, Snap7_buf::NO_COMMUNICATION);
+	m_receive_buf_map[3] = t_snap7_buf;
+
+
+
+//防撞雷达
+	t_index = 0;
+	t_variable_information_vector.clear();
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_response_anticollision_lidar_flag", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 1 });
+	t_index += sizeof(unsigned char)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_reserved5_7", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 3 });
+	t_index += sizeof(unsigned char)*3;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_response_offset_x", typeid(float).name(), t_index,sizeof(float), 1 });
+	t_index += sizeof(float)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_response_offset_angle", typeid(float).name(), t_index,sizeof(float), 1 });
+	t_index += sizeof(float)*1;
+
+//	t_snap7_buf.init(ANTICOLLISION_LIDAR_RESPONSE_FROM_MANAGER_TO_PLC_DBNUMBER_0 +m_plc_id*100, 4, sizeof(Anticollision_lidar_response_from_manager_to_plc_for_data), t_variable_information_vector, Snap7_buf::LOOP_COMMUNICATION);
+	t_snap7_buf.init(ANTICOLLISION_LIDAR_RESPONSE_FROM_MANAGER_TO_PLC_DBNUMBER_0 , 4, sizeof(Anticollision_lidar_response_from_manager_to_plc_for_data), t_variable_information_vector, Snap7_buf::LOOP_COMMUNICATION);
+	m_send_buf_map[7] = t_snap7_buf;
+
+	t_index = 0;
+	t_variable_information_vector.clear();
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_heartbeat", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 1 });
+	t_index += sizeof(unsigned char)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_communication_mode", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 1 });
+	t_index += sizeof(unsigned char)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_refresh_command", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 1 });
+	t_index += sizeof(unsigned char)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_data_validity", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 1 });
+	t_index += sizeof(unsigned char)*1;
+
+//	t_snap7_buf.init(ANTICOLLISION_LIDAR_RESPONSE_FROM_MANAGER_TO_PLC_DBNUMBER_0 +m_plc_id*100, 0, sizeof(Anticollision_lidar_response_from_manager_to_plc_for_key), t_variable_information_vector, Snap7_buf::LOOP_COMMUNICATION);
+	t_snap7_buf.init(ANTICOLLISION_LIDAR_RESPONSE_FROM_MANAGER_TO_PLC_DBNUMBER_0 , 0, sizeof(Anticollision_lidar_response_from_manager_to_plc_for_key), t_variable_information_vector, Snap7_buf::LOOP_COMMUNICATION);
+	m_send_buf_map[8] = t_snap7_buf;
+
+
+	t_index = 0;
+	t_variable_information_vector.clear();
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_heartbeat", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 1 });
+	t_index += sizeof(unsigned char)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_communication_mode", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 1 });
+	t_index += sizeof(unsigned char)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_refresh_command", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 1 });
+	t_index += sizeof(unsigned char)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_data_validity", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 1 });
+	t_index += sizeof(unsigned char)*1;
+
+//	t_snap7_buf.init(ANTICOLLISION_LIDAR_REQUEST_FROM_PLC_TO_MANAGER_DBNUMBER_0 +m_plc_id*100, 0, sizeof(Anticollision_lidar_request_from_plc_to_manager), t_variable_information_vector, Snap7_buf::NO_COMMUNICATION);
+	t_snap7_buf.init(ANTICOLLISION_LIDAR_REQUEST_FROM_PLC_TO_MANAGER_DBNUMBER_0 , 0, sizeof(Anticollision_lidar_request_from_plc_to_manager), t_variable_information_vector, Snap7_buf::NO_COMMUNICATION);
+	m_receive_buf_map[4] = t_snap7_buf;
+
+
+
+
+	//单片机指令
+	t_index = 0;
+	t_variable_information_vector.clear();
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_process_status", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 1 });
+	t_index += sizeof(unsigned char)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_process_control", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 1 });
+	t_index += sizeof(unsigned char)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_over_border_status", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 1 });
+	t_index += sizeof(unsigned char)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_car_height_status_current", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 1 });
+	t_index += sizeof(unsigned char)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_car_height_status_passing", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 1 });
+	t_index += sizeof(unsigned char)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_outside_door_status", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 1 });
+	t_index += sizeof(unsigned char)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_outside_door_control", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 1 });
+	t_index += sizeof(unsigned char)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_dispatch_finish_flag", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 1 });
+	t_index += sizeof(unsigned char)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_inside_existence_flag", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 1 });
+	t_index += sizeof(unsigned char)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_outside_existence_flag", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 1 });
+	t_index += sizeof(unsigned char)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_reset_flag", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 1 });
+	t_index += sizeof(unsigned char)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_stop_flag", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 1 });
+	t_index += sizeof(unsigned char)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_error_code", typeid(unsigned int).name(), t_index,sizeof(unsigned int), 1 });
+	t_index += sizeof(unsigned int)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_reserved16_35", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 20 });
+	t_index += sizeof(unsigned char)*20;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_gpio_input", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 16 });
+	t_index += sizeof(unsigned char)*16;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_gpio_output", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 8 });
+	t_index += sizeof(unsigned char)*8;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_reserved60_79", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 20 });
+	t_index += sizeof(unsigned char)*20;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_heartbeat", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 1 });
+	t_index += sizeof(unsigned char)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_communication_mode", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 1 });
+	t_index += sizeof(unsigned char)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_refresh_command", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 1 });
+	t_index += sizeof(unsigned char)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_data_validity", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 1 });
+	t_index += sizeof(unsigned char)*1;
+
+//	t_snap7_buf.init(SINGLECHIP_RESPONSE_FROM_MANAGER_TO_PLC_DBNUMBER_0 +m_plc_id*100, 0, sizeof(Singlechip_response_from_manager_to_plc), t_variable_information_vector, Snap7_buf::LOOP_COMMUNICATION);
+	t_snap7_buf.init(SINGLECHIP_RESPONSE_FROM_MANAGER_TO_PLC_DBNUMBER_0 , 0, sizeof(Singlechip_response_from_manager_to_plc), t_variable_information_vector, Snap7_buf::LOOP_COMMUNICATION);
+	m_send_buf_map[9] = t_snap7_buf;
+//	t_snap7_buf.init(SINGLECHIP_RESPONSE_FROM_MANAGER_TO_PLC_DBNUMBER_1 +m_plc_id*100, 0, sizeof(Singlechip_response_from_manager_to_plc), t_variable_information_vector, Snap7_buf::LOOP_COMMUNICATION);
+	t_snap7_buf.init(SINGLECHIP_RESPONSE_FROM_MANAGER_TO_PLC_DBNUMBER_1 , 0, sizeof(Singlechip_response_from_manager_to_plc), t_variable_information_vector, Snap7_buf::LOOP_COMMUNICATION);
+	m_send_buf_map[10] = t_snap7_buf;
+//	t_snap7_buf.init(SINGLECHIP_RESPONSE_FROM_MANAGER_TO_PLC_DBNUMBER_2 +m_plc_id*100, 0, sizeof(Singlechip_response_from_manager_to_plc), t_variable_information_vector, Snap7_buf::LOOP_COMMUNICATION);
+	t_snap7_buf.init(SINGLECHIP_RESPONSE_FROM_MANAGER_TO_PLC_DBNUMBER_2 , 0, sizeof(Singlechip_response_from_manager_to_plc), t_variable_information_vector, Snap7_buf::LOOP_COMMUNICATION);
+	m_send_buf_map[11] = t_snap7_buf;
+//	t_snap7_buf.init(SINGLECHIP_RESPONSE_FROM_MANAGER_TO_PLC_DBNUMBER_3 +m_plc_id*100, 0, sizeof(Singlechip_response_from_manager_to_plc), t_variable_information_vector, Snap7_buf::LOOP_COMMUNICATION);
+	t_snap7_buf.init(SINGLECHIP_RESPONSE_FROM_MANAGER_TO_PLC_DBNUMBER_3 , 0, sizeof(Singlechip_response_from_manager_to_plc), t_variable_information_vector, Snap7_buf::LOOP_COMMUNICATION);
+	m_send_buf_map[12] = t_snap7_buf;
+
+
+	t_index = 0;
+	t_variable_information_vector.clear();
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_heartbeat", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 1 });
+	t_index += sizeof(unsigned char)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_communication_mode", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 1 });
+	t_index += sizeof(unsigned char)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_refresh_command", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 1 });
+	t_index += sizeof(unsigned char)*1;
+	t_variable_information_vector.push_back(Snap7_buf::Variable_information{"m_data_validity", typeid(unsigned char).name(), t_index,sizeof(unsigned char), 1 });
+	t_index += sizeof(unsigned char)*1;
+
+//	t_snap7_buf.init(SINGLECHIP_REQUEST_FROM_PLC_TO_MANAGER_DBNUMBER_0 +m_plc_id*100, 0, sizeof(Singlechip_request_from_plc_to_manager), t_variable_information_vector, Snap7_buf::NO_COMMUNICATION);
+	t_snap7_buf.init(SINGLECHIP_REQUEST_FROM_PLC_TO_MANAGER_DBNUMBER_0 , 0, sizeof(Singlechip_request_from_plc_to_manager), t_variable_information_vector, Snap7_buf::NO_COMMUNICATION);
+	m_receive_buf_map[5] = t_snap7_buf;
+//	t_snap7_buf.init(SINGLECHIP_REQUEST_FROM_PLC_TO_MANAGER_DBNUMBER_1 +m_plc_id*100, 0, sizeof(Singlechip_request_from_plc_to_manager), t_variable_information_vector, Snap7_buf::NO_COMMUNICATION);
+	t_snap7_buf.init(SINGLECHIP_REQUEST_FROM_PLC_TO_MANAGER_DBNUMBER_1 , 0, sizeof(Singlechip_request_from_plc_to_manager), t_variable_information_vector, Snap7_buf::NO_COMMUNICATION);
+	m_receive_buf_map[6] = t_snap7_buf;
+//	t_snap7_buf.init(SINGLECHIP_REQUEST_FROM_PLC_TO_MANAGER_DBNUMBER_2 +m_plc_id*100, 0, sizeof(Singlechip_request_from_plc_to_manager), t_variable_information_vector, Snap7_buf::NO_COMMUNICATION);
+	t_snap7_buf.init(SINGLECHIP_REQUEST_FROM_PLC_TO_MANAGER_DBNUMBER_2 , 0, sizeof(Singlechip_request_from_plc_to_manager), t_variable_information_vector, Snap7_buf::NO_COMMUNICATION);
+	m_receive_buf_map[7] = t_snap7_buf;
+//	t_snap7_buf.init(SINGLECHIP_REQUEST_FROM_PLC_TO_MANAGER_DBNUMBER_3 +m_plc_id*100, 0, sizeof(Singlechip_request_from_plc_to_manager), t_variable_information_vector, Snap7_buf::NO_COMMUNICATION);
+	t_snap7_buf.init(SINGLECHIP_REQUEST_FROM_PLC_TO_MANAGER_DBNUMBER_3 , 0, sizeof(Singlechip_request_from_plc_to_manager), t_variable_information_vector, Snap7_buf::NO_COMMUNICATION);
+	m_receive_buf_map[8] = t_snap7_buf;
+
+	switch ( m_plc_id )
+	{
+	    case 0:
+	    {
+			return Snap7_communication_base::communication_init_from_protobuf(SNAP7_COMMUNICATION_PARAMETER_PATH_A);
+	        break;
+	    }
+		case 1:
+	    {
+			return Snap7_communication_base::communication_init_from_protobuf(SNAP7_COMMUNICATION_PARAMETER_PATH_B);
+	        break;
+	    }
+		case 2:
+		{
+			return Snap7_communication_base::communication_init_from_protobuf(SNAP7_COMMUNICATION_PARAMETER_PATH_C);
+			break;
+		}
+	    default:
+	    {
+	        return Error_manager(Error_code::SNAP7_READ_PROTOBUF_ERROR, Error_level::MINOR_ERROR,
+	        					" Dispatch_communication::communication_init m_plc_id error ");
+	        break;
+	    }
+	}
+
+
+}
+
+//反初始化 通信 模块。
+Error_manager Dispatch_communication::communication_uninit()
+{
+	return Snap7_communication_base::communication_uninit();
+}
+
+
+//更新数据
+Error_manager Dispatch_communication::updata_receive_buf()
+{
+//	return Error_code::SUCCESS;
+	std::unique_lock<std::mutex> t_lock1(m_receive_buf_lock);
+	std::unique_lock<std::mutex> t_lock2(m_data_lock);
+
+	memcpy(&m_dispatch_response_from_plc_to_manager, m_receive_buf_map[0].mp_buf_obverse, m_receive_buf_map[0].m_size);
+
+	memcpy(&m_dispatch_plc_status_from_plc_to_manager, m_receive_buf_map[1].mp_buf_obverse, m_receive_buf_map[1].m_size);
+
+	memcpy(&m_ground_lidar_request_from_plc_to_manager[0], m_receive_buf_map[2].mp_buf_obverse, m_receive_buf_map[2].m_size);
+	memcpy(&m_ground_lidar_request_from_plc_to_manager[1], m_receive_buf_map[3].mp_buf_obverse, m_receive_buf_map[3].m_size);
+
+	memcpy(&m_anticollision_lidar_request_from_plc_to_manager, m_receive_buf_map[4].mp_buf_obverse, m_receive_buf_map[4].m_size);
+
+	memcpy(&m_singlechip_request_from_plc_to_manager[0], m_receive_buf_map[5].mp_buf_obverse, m_receive_buf_map[5].m_size);
+	memcpy(&m_singlechip_request_from_plc_to_manager[1], m_receive_buf_map[6].mp_buf_obverse, m_receive_buf_map[6].m_size);
+	memcpy(&m_singlechip_request_from_plc_to_manager[3], m_receive_buf_map[7].mp_buf_obverse, m_receive_buf_map[7].m_size);
+	memcpy(&m_singlechip_request_from_plc_to_manager[4], m_receive_buf_map[8].mp_buf_obverse, m_receive_buf_map[8].m_size);
+
+
+	return Error_code::SUCCESS;
+}
+Error_manager Dispatch_communication::updata_send_buf()
+{
+	std::unique_lock<std::mutex> t_lock1(m_send_buf_lock);
+	std::unique_lock<std::mutex> t_lock2(m_data_lock);
+
+	memcpy(m_send_buf_map[0].mp_buf_obverse, &m_dispatch_request_from_manager_to_plc_for_data, m_send_buf_map[0].m_size);
+	memcpy(m_send_buf_map[1].mp_buf_obverse, &m_dispatch_request_from_manager_to_plc_for_key, m_send_buf_map[1].m_size);
+	memcpy(m_send_buf_map[2].mp_buf_obverse, &m_dispatch_plc_status_from_manager_to_plc, m_send_buf_map[2].m_size);
+
+	memcpy(m_send_buf_map[3].mp_buf_obverse, &m_ground_lidar_response_from_manager_to_plc_for_data[0], m_send_buf_map[3].m_size);
+	memcpy(m_send_buf_map[4].mp_buf_obverse, &m_ground_lidar_response_from_manager_to_plc_for_data[1], m_send_buf_map[4].m_size);
+	memcpy(m_send_buf_map[5].mp_buf_obverse, &m_ground_lidar_response_from_manager_to_plc_for_key[0], m_send_buf_map[5].m_size);
+	memcpy(m_send_buf_map[6].mp_buf_obverse, &m_ground_lidar_response_from_manager_to_plc_for_key[1], m_send_buf_map[6].m_size);
+
+	memcpy(m_send_buf_map[7].mp_buf_obverse, &m_anticollision_lidar_response_from_manager_to_plc_for_data, m_send_buf_map[7].m_size);
+	memcpy(m_send_buf_map[8].mp_buf_obverse, &m_anticollision_lidar_response_from_manager_to_plc_for_key, m_send_buf_map[8].m_size);
+
+	memcpy(m_send_buf_map[9].mp_buf_obverse, &m_singlechip_response_from_manager_to_plc[0], m_send_buf_map[9].m_size);
+	memcpy(m_send_buf_map[10].mp_buf_obverse, &m_singlechip_response_from_manager_to_plc[1], m_send_buf_map[10].m_size);
+	memcpy(m_send_buf_map[11].mp_buf_obverse, &m_singlechip_response_from_manager_to_plc[2], m_send_buf_map[11].m_size);
+	memcpy(m_send_buf_map[12].mp_buf_obverse, &m_singlechip_response_from_manager_to_plc[3], m_send_buf_map[12].m_size);
+
+//	std::cout << " huli test :::: " << " m_dispatch_request_from_manager_to_plc_for_data = " << m_dispatch_request_from_manager_to_plc_for_data.m_request_car_center_x << std::endl;
+	return Error_code::SUCCESS;
+}
+
+
+
+

+ 666 - 0
plc调度节点/dispatch/dispatch_communication.h

@@ -0,0 +1,666 @@
+//
+// Created by huli on 2020/9/25.
+//
+
+#ifndef NNXX_TESTS_DISPATCH_COMMUNICATION_H
+#define NNXX_TESTS_DISPATCH_COMMUNICATION_H
+
+#include "../tool/singleton.h"
+#include "../snap7_communication/snap7_communication_base.h"
+
+class Dispatch_communication:public Singleton<Dispatch_communication>, public Snap7_communication_base
+{
+public:
+	//发送db快的标记位, 保证先发数据再发唯一码
+	enum Send_database_flag
+	{
+		E_SEND_UNKNOW					= 0,
+		E_SEND_DATA_START              	= 1,    //开始发送数据
+		E_SEND_DATA_END              	= 2,    //结束发送数据
+		E_SEND_KEY_START				= 3,	//开始发送唯一码
+		E_SEND_KEY_END					= 4,	//结束发送唯一码
+	};
+
+
+#pragma pack(push, 1)	//struct按照1个byte对齐
+
+	//抓车模块给plc发送请求消息的DB编号
+#define CATCHER_REQUEST_FROM_DISPATCH_TO_PLC_DBNUMBER_1		110
+#define CATCHER_REQUEST_FROM_DISPATCH_TO_PLC_DBNUMBER_2		120
+	//抓车模块给plc发送请求消息的指令结构体
+	struct Catcher_request_from_dispatch_to_plc_for_data
+	{
+		//指令信息
+		unsigned char			m_reserved50 = 0;					//预留
+		unsigned char			m_reserved51_69[19] = {0};	//预留
+		// 请求的目标坐标和动作
+		float 					m_request_x = 0;				//机器人坐标x轴,
+		float 					m_request_y = 0;				//机器人坐标y轴,
+		float 					m_request_b = 0;				//机器人坐标b轴, 旋转范围80~280
+		float 					m_request_z = 0;				//机器人坐标z轴,
+		unsigned char			m_request_clamp_motion = 0;		//机器人夹车杆. 0=无动作,1=夹紧,2=松开
+		unsigned char			m_reserved87_89[3] = {0};			//预留
+		float 					m_request_wheelbase = 0;		//机器人抓车杆前后轮距.
+		float 					m_request_d1 = 0;				//机器人坐标d1轴, 机器人抓车杆纵向移动(前轮抓杆)
+		float 					m_request_d2 = 0;				//机器人坐标d2轴, 机器人抓车杆纵向移动(后轮抓杆)
+	};
+
+	//抓车模块给plc发送请求消息的指令结构体
+	struct Catcher_request_from_dispatch_to_plc_for_key
+	{
+		//指令信息
+		unsigned char			m_request_key[50] = {0};		//指令key(任务唯一码), 作为通信标志位
+	};
+
+	//plc给抓车模块发送答复消息的DB编号
+#define CATCHER_RESPONSE_FROM_PLC_TO_DISPATCH_DBNUMBER_1		111
+#define CATCHER_RESPONSE_FROM_PLC_TO_DISPATCH_DBNUMBER_2		121
+	//plc给抓车模块发送答复消息的指令结构体
+	struct Catcher_response_from_plc_to_dispatch
+	{
+		//指令信息
+		unsigned char			m_respons_key[50] = {0};		//指令key(任务唯一码), 作为通信标志位
+		unsigned char			m_respons_status = 0;			//指令完成状态, 机器人答复指令, 返回任务完成的情况
+		unsigned char			m_reserved51_69[19] = {0};	//预留
+		//请求的目标坐标和动作
+		float 					m_respons_x = 0;				//机器人坐标x轴,
+		float 					m_respons_y = 0;				//机器人坐标y轴,
+		float 					m_respons_b = 0;				//机器人坐标b轴, 旋转范围80~280
+		float 					m_respons_z = 0;				//机器人坐标z轴,
+		unsigned char			m_respons_clamp_motion = 0;		//机器人夹车杆. 0=无动作,1=夹紧,2=松开
+		unsigned char			m_reserved87_89[3] = {0};			//预留
+		float 					m_respons_wheelbase = 0;		//机器人抓车杆前后轮距.
+		float 					m_respons_d1 = 0;				//机器人坐标d1轴, 机器人抓车杆纵向移动(前轮抓杆)
+		float 					m_respons_d2 = 0;				//机器人坐标d2轴, 机器人抓车杆纵向移动(后轮抓杆)
+	};
+
+	//plc给抓车模块发送状态消息的DB编号
+#define CATCHER_STATUS_FROM_PLC_TO_DISPATCH_DBNUMBER_1		113
+#define CATCHER_STATUS_FROM_PLC_TO_DISPATCH_DBNUMBER_2		123
+	//plc给抓车模块发送状态消息的指令结构体
+	struct Catcher_status_from_plc_to_dispatch
+	{
+		unsigned char			m_heartbeat = 0;				//心跳位, 0-255循环
+
+		unsigned char			m_safe_status = 0;				//设备的安全状态
+		unsigned char			m_work_status = 0;				//机器人的硬件设备状态
+		unsigned char			m_actual_load_status = 0;		//机器人的负载状态, 机器人上面是否有车.
+		unsigned char			m_reserved4_37[34] = {0};		//预留
+
+		float 					m_actual_x = 0;					//机器人坐标x轴,
+		float 					m_actual_y = 0;					//机器人坐标y轴,
+		float 					m_actual_b = 0;					//机器人坐标b轴, 旋转范围80~280
+		float 					m_actual_z = 0;					//机器人坐标z轴,
+		float 					m_actual_d1 = 0;				//机器人坐标d1轴, 机器人抓车杆纵向移动(前轮抓杆)
+		float 					m_actual_d2 = 0;				//机器人坐标d2轴, 机器人抓车杆纵向移动(后轮抓杆)
+		unsigned char			m_actual_clamp_motion1 = 0;		//机器人夹车杆. 0=无动作,1=夹紧,2=松开
+		unsigned char			m_actual_clamp_motion2 = 0;		//机器人夹车杆. 0=无动作,1=夹紧,2=松开
+		unsigned char			m_actual_clamp_motion3 = 0;		//机器人夹车杆. 0=无动作,1=夹紧,2=松开
+		unsigned char			m_actual_clamp_motion4 = 0;		//机器人夹车杆. 0=无动作,1=夹紧,2=松开
+		unsigned char			m_reserved66_99[34] = {0};		//预留
+
+		//故障信息
+		unsigned char			m_actual_error_code[50] = {0};		//搬运器错误码
+		unsigned char			m_actual_warning_code[50] = {0};	//升降机错误码
+		unsigned char			m_actual_error_description[256] = {0};	//升降机错误描述
+	};
+
+
+
+
+
+	//搬运器给plc发送请求消息的DB编号
+#define CARRIER_REQUEST_FROM_DISPATCH_TO_PLC_DBNUMBER_1		200
+#define CARRIER_REQUEST_FROM_DISPATCH_TO_PLC_DBNUMBER_2		270
+#define CARRIER_REQUEST_FROM_DISPATCH_TO_PLC_DBNUMBER_3		230
+	//搬运器给plc发送请求消息的指令结构体
+	struct Carrier_request_from_dispatch_to_plc_for_data
+	{
+		//指令信息
+		unsigned char						m_reserved50 = 0;			//预留
+		unsigned char						m_reserved51_71[21] = {0};	//预留
+		//请求的目标坐标和动作
+		float 								m_request_x;				//搬运器坐标x轴, 中跑车控制横向移动
+		float 								m_request_y;				//搬运器坐标y轴, 小跑车控制纵向移动
+		float 								m_request_z;				//搬运器坐标z轴, 电梯控制上下移动
+		float 								m_request_y1;				//搬运器坐标y1轴, 小跑车控制纵向移动(前轮抓杆)
+		float 								m_request_y2;				//搬运器坐标y2轴, 小跑车控制纵向移动(后轮抓杆)
+		unsigned char						m_request_clamp_motion;		//小跑车夹车杆. 0=无动作,1=夹紧,2=松开
+		unsigned char						m_request_joint_motion_x;	//电梯与X轴的横向轨道对接,0=无动作,1=进行对接, 2=松开对接
+		unsigned char						m_request_joint_motion_y;	//小跑车与Y轴的横向轨道对接,0=无动作,1=进行对接, 2=松开对接
+		unsigned char						m_reserved95 = 0;					//预留
+		int 								m_request_space_id;			//搬运器空间位置的id.
+		int 								m_request_floor_id;			//搬运器楼层位置的id.
+		float 								m_request_wheelbase;		//搬运器小跑车的抓车杆前后轮距.
+	};
+
+	//搬运器给plc发送请求消息的指令结构体
+	struct Carrier_request_from_dispatch_to_plc_for_key
+	{
+		//指令信息
+		unsigned char						m_request_key[50] = {0};		//指令key(任务唯一码), 作为通信标志位
+	};
+
+	//plc给搬运器发送答复消息的DB编号
+#define CARRIER_RESPONSE_FROM_PLC_TO_DISPATCH_DBNUMBER_1		201
+#define CARRIER_RESPONSE_FROM_PLC_TO_DISPATCH_DBNUMBER_2		271
+#define CARRIER_RESPONSE_FROM_PLC_TO_DISPATCH_DBNUMBER_3		231
+	//plc给搬运器发送答复消息的指令结构体
+	struct Carrier_response_from_plc_to_dispatch
+	{
+		//指令信息
+		unsigned char						m_respons_key[50] = {0};	//指令key(任务唯一码), 作为通信标志位
+		unsigned char						m_respons_status = 0;		//指令完成状态, 机器人答复指令, 返回任务完成的情况
+		unsigned char						m_reserved51_71[21] = {0};	//预留
+		//请求的目标坐标和动作
+		float 								m_respons_x;				//搬运器坐标x轴, 中跑车控制横向移动
+		float 								m_respons_y;				//搬运器坐标y轴, 小跑车控制纵向移动
+		float 								m_respons_z;				//搬运器坐标z轴, 电梯控制上下移动
+		float 								m_respons_y1;				//搬运器坐标y1轴, 小跑车控制纵向移动(前轮抓杆)
+		float 								m_respons_y2;				//搬运器坐标y2轴, 小跑车控制纵向移动(后轮抓杆)
+		unsigned char						m_respons_clamp_motion;		//小跑车夹车杆. 0=无动作,1=夹紧,2=松开
+		unsigned char						m_respons_joint_motion_x;	//电梯与X轴的横向轨道对接,0=无动作,1=进行对接, 2=松开对接
+		unsigned char						m_respons_joint_motion_y;	//小跑车与Y轴的横向轨道对接,0=无动作,1=进行对接, 2=松开对接
+		unsigned char						m_reserved95 = 0;					//预留
+		int 								m_respons_space_id;			//搬运器空间位置的id.
+		int 								m_respons_floor_id;			//搬运器楼层位置的id.
+		float 								m_respons_wheelbase;		//搬运器小跑车的抓车杆前后轮距.
+	};
+
+	//plc给搬运器发送状态消息的DB编号
+#define CARRIER_STATUS_FROM_PLC_TO_DISPATCH_DBNUMBER_1		203
+#define CARRIER_STATUS_FROM_PLC_TO_DISPATCH_DBNUMBER_2		273
+#define CARRIER_STATUS_FROM_PLC_TO_DISPATCH_DBNUMBER_3		233
+	//plc给搬运器发送状态消息的指令结构体
+	struct Carrier_status_from_plc_to_dispatch
+	{
+		unsigned char			m_heartbeat = 0;				//心跳位, 0-255循环
+
+		unsigned char			m_safe_status = 0;				//设备的安全状态
+		unsigned char			m_work_status = 0;				//搬运器的硬件设备状态
+		unsigned char			m_actual_load_status = 0;		//搬运器的负载状态, 小跑车上面是否有车.
+		unsigned char			m_reserved4_37[34] = {0};		//预留
+
+		float 					m_actual_x = 0;					//搬运器坐标x轴,
+		float 					m_actual_y = 0;					//搬运器坐标y轴,
+		float 					m_actual_z = 0;					//搬运器坐标z轴,
+		float 					m_actual_y1 = 0;				//搬运器坐标y1轴, 小跑车控制纵向移动(前轮抓杆)
+		float 					m_actual_y2 = 0;				//搬运器坐标y2轴, 小跑车控制纵向移动(前轮抓杆)
+		unsigned char			m_actual_clamp_motion1 = 0;		//小跑车夹车杆. 0=无动作,1=夹紧,2=松开
+		unsigned char			m_actual_clamp_motion2 = 0;		//小跑车夹车杆. 0=无动作,1=夹紧,2=松开
+		unsigned char			m_actual_small_sports_car_motion = 0;		//小跑车的位置,是否在中跑车上面, 0=无动作,1=出发到位,2=返回到位
+		unsigned char			m_actual_joint_motion_x1 = 0;		//电梯与X轴的横向轨道对接,0=无动作,1=伸出到位,2=收回到位
+		unsigned char			m_actual_joint_motion_x2 = 0;		//电梯与X轴的横向轨道对接,0=无动作,1=伸出到位,2=收回到位
+		unsigned char			m_reserved63_101[39] = {0};		//预留
+		//故障信息
+		unsigned char			m_actual_error_code[50] = {0};		//搬运器错误码
+		unsigned char			m_actual_warning_code[50] = {0};	//升降机错误码
+		unsigned char			m_actual_error_description[256] = {0};	//升降机错误描述
+	};
+
+
+
+
+
+
+
+
+	//通道口给plc发送请求消息的DB编号
+#define PASSAGEWAY_REQUEST_FROM_DISPATCH_TO_PLC_DBNUMBER_0		300
+#define PASSAGEWAY_REQUEST_FROM_DISPATCH_TO_PLC_DBNUMBER_1		310
+#define PASSAGEWAY_REQUEST_FROM_DISPATCH_TO_PLC_DBNUMBER_2		320
+#define PASSAGEWAY_REQUEST_FROM_DISPATCH_TO_PLC_DBNUMBER_3		330
+#define PASSAGEWAY_REQUEST_FROM_DISPATCH_TO_PLC_DBNUMBER_4		340
+#define PASSAGEWAY_REQUEST_FROM_DISPATCH_TO_PLC_DBNUMBER_5		350
+#define PASSAGEWAY_REQUEST_FROM_DISPATCH_TO_PLC_DBNUMBER_6		360
+#define PASSAGEWAY_REQUEST_FROM_DISPATCH_TO_PLC_DBNUMBER_7		370
+
+	//通道口给plc发送请求消息的指令结构体
+	struct Passageway_request_from_dispatch_to_plc_for_data
+	{
+		//指令信息
+		unsigned char			m_reserved50 = 0;					//预留
+		unsigned char			m_reserved51_69[19] = {0};	//预留
+		// 请求的目标坐标和动作
+		unsigned char			m_request_inside_door_motion = 0;		//通道口 内门动作
+		unsigned char			m_request_outside_door_motion = 0;		//通道口 外门动作
+		unsigned char			m_request_turntable_direction = 0;		//通道口 转台方向
+	};
+
+	//通道口给plc发送请求消息的指令结构体
+	struct Passageway_request_from_dispatch_to_plc_for_key
+	{
+		//指令信息
+		unsigned char						m_request_key[50] = {0};		//指令key(任务唯一码), 作为通信标志位
+	};
+
+	//plc给通道口发送答复消息的DB编号
+#define PASSAGEWAY_RESPONSE_FROM_PLC_TO_DISPATCH_DBNUMBER_0		301
+#define PASSAGEWAY_RESPONSE_FROM_PLC_TO_DISPATCH_DBNUMBER_1		311
+#define PASSAGEWAY_RESPONSE_FROM_PLC_TO_DISPATCH_DBNUMBER_2		321
+#define PASSAGEWAY_RESPONSE_FROM_PLC_TO_DISPATCH_DBNUMBER_3		331
+#define PASSAGEWAY_RESPONSE_FROM_PLC_TO_DISPATCH_DBNUMBER_4		341
+#define PASSAGEWAY_RESPONSE_FROM_PLC_TO_DISPATCH_DBNUMBER_5		351
+#define PASSAGEWAY_RESPONSE_FROM_PLC_TO_DISPATCH_DBNUMBER_6		361
+#define PASSAGEWAY_RESPONSE_FROM_PLC_TO_DISPATCH_DBNUMBER_7		371
+
+	//plc给通道口发送答复消息的指令结构体
+	struct Passageway_response_from_plc_to_dispatch
+	{
+		//指令信息
+		unsigned char						m_respons_key[50] = {0};	//指令key(任务唯一码), 作为通信标志位
+		unsigned char						m_respons_status = 0;		//指令完成状态, 机器人答复指令, 返回任务完成的情况
+		unsigned char						m_reserved51_69[19] = {0};	//预留
+
+		unsigned char			m_respons_inside_door_motion = 0;		//通道口 内门动作
+		unsigned char			m_respons_outside_door_motion = 0;		//通道口 外门动作
+		unsigned char			m_respons_turntable_direction = 0;		//通道口 转台方向
+	};
+
+	//plc给通道口发送状态消息的DB编号
+#define PASSAGEWAY_STATUS_FROM_PLC_TO_DISPATCH_DBNUMBER_0		303
+#define PASSAGEWAY_STATUS_FROM_PLC_TO_DISPATCH_DBNUMBER_1		313
+#define PASSAGEWAY_STATUS_FROM_PLC_TO_DISPATCH_DBNUMBER_2		323
+#define PASSAGEWAY_STATUS_FROM_PLC_TO_DISPATCH_DBNUMBER_3		333
+#define PASSAGEWAY_STATUS_FROM_PLC_TO_DISPATCH_DBNUMBER_4		343
+#define PASSAGEWAY_STATUS_FROM_PLC_TO_DISPATCH_DBNUMBER_5		353
+#define PASSAGEWAY_STATUS_FROM_PLC_TO_DISPATCH_DBNUMBER_6		363
+#define PASSAGEWAY_STATUS_FROM_PLC_TO_DISPATCH_DBNUMBER_7		373
+
+	//plc给通道口发送状态消息的指令结构体
+	struct Passageway_status_from_plc_to_dispatch
+	{
+		unsigned char			m_heartbeat = 0;				//心跳位, 0-255循环
+
+		unsigned char			m_safe_status = 0;				//设备的安全状态
+		unsigned char			m_sensor_status1 = 0;			//设备的传感器状态1
+		unsigned char			m_sensor_status2 = 0;			//设备的传感器状态2
+		unsigned char			m_reserved4_35[32] = {0};		//预留
+		unsigned char			m_actual_turntable_direction;	//通道口 转台方向
+		unsigned char			m_reserved37 = 0;					//预留
+
+		//故障信息
+		unsigned char			m_actual_error_code[50] = {0};		//通道口错误码
+		unsigned char			m_actual_warning_code[50] = {0};	//升降机错误码
+		unsigned char			m_actual_error_description[256] = {0};	//升降机错误描述
+	};
+
+
+
+
+
+
+
+
+
+	//snap7的通信参数路径
+#define SNAP7_COMMUNICATION_PARAMETER_PATH_A	"../setting/snap7_communication_a.prototxt"
+#define SNAP7_COMMUNICATION_PARAMETER_PATH_B	"../setting/snap7_communication_b.prototxt"
+#define SNAP7_COMMUNICATION_PARAMETER_PATH_C	"../setting/snap7_communication_c.prototxt"
+
+
+
+//调度管理给plc发送调度指令 的DB编号
+#define DISPATCH_REQUEST_FROM_MANAGER_TO_PLC_DBNUMBER_0		9000
+//调度管理给plc发送调度指令 的结构体
+	struct Dispatch_request_from_manager_to_plc_for_data
+	{
+		//指令信息
+		unsigned char			m_request_status = 0;			//指令完成状态, 机器人答复指令, 返回任务完成的情况
+		unsigned char			m_reserved51 = 0;				//预留
+		float					m_request_working_total_time;				//搬运总时间(秒)
+		float					m_request_working_remaining_time;			//剩余时间(秒)
+		unsigned char			m_reserved60_73[14] = {0};			//预留
+		// 调度指令的起点,终点,方向
+		unsigned char			m_request_dispatch_motion_direction = 0;			//调度方向	0=未知,1=存车,2=取车
+		unsigned char			m_reserved75_79[5] = {0};							//预留
+		unsigned int			m_request_passageway_id = 0;						//出入口id	6个入口和6个出口
+		unsigned char			m_request_passageway_direction = 0;				//出入口方向	0=未知,1=入口,2=出口
+		unsigned char			m_reserved85_89[5] = {0};							//预留
+		unsigned int			m_request_parkingspace_index_id = 0;				//楼上车位索引id	1~180(3*6*13)
+		unsigned int			m_request_parkingspace_unit_id = 0;				//楼上车位单元号	1~3
+		unsigned int			m_request_parkingspace_label_id = 0;				//楼上车位标签号	1~78
+		unsigned int			m_request_parkingspace_floor_id = 0;				//楼上车位楼层号	2~11
+		unsigned int			m_request_parkingspace_room_id = 0;				//楼上车位房间号	1~6
+		unsigned char			m_request_parkingspace_direction = 0;				//楼上车位方向	0=未知,1=朝南,2=朝北
+		unsigned char			m_reserved111 = 0;							//预留
+
+		//汽车的定位信息(地面雷达)
+		float 					m_request_car_center_x = 0;				//整车的中心点x值, 四轮的中心, 单位:米 m
+		float  					m_request_car_center_y = 0;				//整车的中心点y值, 四轮的中心, 单位:米 m
+		float  					m_request_car_angle = 0;					//整车的车身旋转角, 单位:度 (-90~90)
+		float  					m_request_car_front_theta = 0;				//整车的前轮的旋转角, 单位:度 (-90~90)
+		float  					m_request_car_length = 0;					//整车的长度, 用于规避碰撞, 单位:米 m
+		float  					m_request_car_width = 0;					//整车的宽度, 用于规避碰撞, 单位:米 m
+		float  					m_request_car_height = 0;					//整车的高度, 用于规避碰撞, 单位:米 m
+		float  					m_request_car_wheel_base = 0;				//整车的轮距, 前后轮的距离, 用于机器人或agv的抓车, 单位:米 m
+		float  					m_request_car_wheel_width = 0;				//整车的轮距, 左右轮的距离, 用于机器人或agv的抓车, 单位:米 m
+		unsigned char			m_request_car_license[20] = {0};			//车牌号(汽车唯一标示)	例如: 鄂A12345
+		unsigned char			m_reserved168_187[20] = {0};							//预留
+
+		unsigned char			m_request_car_type = 0;						//0=未知,1=小车,2=中车,3=大车 ..188
+		unsigned char			m_reserved189_191[3] = {0};							//预留
+
+		float					m_request_uniformed_car_x = 0;					//转角复位后,车辆中心点x
+		float					m_request_uniformed_car_y = 0;					//转角复位后,车辆中心点y
+		unsigned char			m_reserved200_209[10] = {0};							//预留
+
+		//防撞雷达 ..210
+		unsigned char			m_request_anticollision_lidar_flag = 0;		//汽车是否停到正确的位置, 防撞雷达	预留, 楚天暂时不用,0=未知,1=位置正常,2=位置异常
+		unsigned char			m_reserved211_215[5] = {0};							//预留
+		//轮距雷达 ..216
+		float  					m_request_car_wheel_base_exact_value = 0;	//汽车前后轮距,轮距雷达的精确值	预留, 楚天暂时不用,单位:米 m
+		unsigned char			m_reserved220_231[12] = {0};				//预留
+
+	};
+//调度管理给plc发送调度指令 的结构体
+	struct Dispatch_request_from_manager_to_plc_for_key
+	{
+		//指令信息
+		unsigned char						m_request_key[50] = {0};		//指令key(任务唯一码), 作为通信标志位
+	};
+
+//plc给调度管理发送调度答复 的DB编号
+#define DISPATCH_RESPONSE_FROM_PLC_TO_MANAGER_DBNUMBER_0		9001
+//plc给调度管理发送调度答复 的结构体
+	struct Dispatch_response_from_plc_to_manager
+	{
+		unsigned char						m_response_key[50] = {0};		//指令key(任务唯一码), 作为通信标志位
+
+		//指令信息
+		unsigned char			m_response_status = 0;			//指令完成状态, 机器人答复指令, 返回任务完成的情况
+		unsigned char			m_reserved51 = 0;				//预留
+		float					m_response_working_total_time;				//搬运总时间(秒)
+		float					m_response_working_remaining_time;			//剩余时间(秒)
+		unsigned char			m_reserved60_73[14] = {0};			//预留
+		// 调度指令的起点,终点,方向
+		unsigned char			m_response_dispatch_motion_direction = 0;			//调度方向	0=未知,1=存车,2=取车
+		unsigned char			m_reserved75_79[5] = {0};							//预留
+		unsigned int			m_response_passageway_id = 0;						//出入口id	6个入口和6个出口
+		unsigned char			m_response_passageway_direction = 0;				//出入口方向	0=未知,1=入口,2=出口
+		unsigned char			m_reserved85_89[5] = {0};							//预留
+		unsigned int			m_response_parkingspace_index_id = 0;				//楼上车位索引id	1~180(3*6*13)
+		unsigned int			m_response_parkingspace_unit_id = 0;				//楼上车位单元号	1~3
+		unsigned int			m_response_parkingspace_label_id = 0;				//楼上车位标签号	1~78
+		unsigned int			m_response_parkingspace_floor_id = 0;				//楼上车位楼层号	2~11
+		unsigned int			m_response_parkingspace_room_id = 0;				//楼上车位房间号	1~6
+		unsigned char			m_response_parkingspace_direction = 0;				//楼上车位方向	0=未知,1=朝南,2=朝北
+		unsigned char			m_reserved111 = 0;							//预留
+
+		//汽车的定位信息(地面雷达)
+		float 					m_response_car_center_x = 0;				//整车的中心点x值, 四轮的中心, 单位:米 m
+		float  					m_response_car_center_y = 0;				//整车的中心点y值, 四轮的中心, 单位:米 m
+		float  					m_response_car_angle = 0;					//整车的车身旋转角, 单位:度 (-90~90)
+		float  					m_response_car_front_theta = 0;				//整车的前轮的旋转角, 单位:度 (-90~90)
+		float  					m_response_car_length = 0;					//整车的长度, 用于规避碰撞, 单位:米 m
+		float  					m_response_car_width = 0;					//整车的宽度, 用于规避碰撞, 单位:米 m
+		float  					m_response_car_height = 0;					//整车的高度, 用于规避碰撞, 单位:米 m
+		float  					m_response_car_wheel_base = 0;				//整车的轮距, 前后轮的距离, 用于机器人或agv的抓车, 单位:米 m
+		float  					m_response_car_wheel_width = 0;				//整车的轮距, 左右轮的距离, 用于机器人或agv的抓车, 单位:米 m
+		unsigned char			m_response_car_license[20] = {0};			//车牌号(汽车唯一标示)	例如: 鄂A12345
+		unsigned char			m_reserved168_187[20] = {0};							//预留
+
+		unsigned char			m_response_car_type = 0;						//0=未知,1=小车,2=中车,3=大车 ..188
+		unsigned char			m_reserved189_191[3] = {0};							//预留
+
+		float					m_response_uniformed_car_x = 0;					//转角复位后,车辆中心点x
+		float					m_response_uniformed_car_y = 0;					//转角复位后,车辆中心点y
+		unsigned char			m_reserved200_209[10] = {0};							//预留
+		//防撞雷达 ..210
+		unsigned char			m_response_anticollision_lidar_flag = 0;		//汽车是否停到正确的位置, 防撞雷达	预留, 楚天暂时不用,0=未知,1=位置正常,2=位置异常
+		unsigned char			m_reserved211_215[5] = {0};							//预留
+		//轮距雷达 ..216
+		float  					m_response_car_wheel_base_exact_value = 0;	//汽车前后轮距,轮距雷达的精确值	预留, 楚天暂时不用,单位:米 m
+		unsigned char			m_reserved220_231[12] = {0};				//预留
+
+	};
+
+	//调度管理的的状态信息 的DB编号
+#define DISPATCH_PLC_STATUS_FROM_MANAGER_TO_PLC_DBNUMBER_0		9002
+//调度管理给plc发送状态消息的指令结构体
+	struct Dispatch_plc_status_from_manager_to_plc
+	{
+		unsigned char			m_dispatch_heartbeat = 0;				//心跳位, 0-255循环
+
+	};
+
+	//plc的状态信息 的DB编号
+#define DISPATCH_PLC_STATUS_FROM_PLC_TO_MANAGER_DBNUMBER_0		9003
+//plc给通道口发送状态消息的指令结构体
+	struct Dispatch_plc_status_from_plc_to_manager
+	{
+		unsigned char			m_plc_heartbeat = 0;				//心跳位, 0-255循环
+		unsigned char			m_plc_status_info = 0;			//plc状态的集合
+		//0 bit, 手动模式
+		//1 bit, 自动模式
+		//2 bit, 自动运行中
+		//3 bit, 复位
+		//4 bit, 1号口可以进车
+		//5 bit, 2号口可以进车
+		//6 bit, 预留
+		//7 bit, 预留
+		unsigned char			m_reserved2_37[36] = {0};		//预留 36个
+		float					m_turnplate_angle_min1 = 0;		//1号口转盘最小值
+		float					m_turnplate_angle_max1 = 0;		//1号口转盘最大值
+		float					m_turnplate_angle_min2 = 0;		//2号口转盘最小值
+		float					m_turnplate_angle_max2 = 0;		//2号口转盘最大值
+
+
+	};
+
+
+
+
+
+
+
+	//地面雷达给plc
+#define GROUND_LIDAR_RESPONSE_FROM_MANAGER_TO_PLC_DBNUMBER_0		9004
+#define GROUND_LIDAR_RESPONSE_FROM_MANAGER_TO_PLC_DBNUMBER_1		9014
+	struct Ground_lidar_response_from_manager_to_plc_for_key
+	{
+		unsigned char			m_response_heartbeat = 0;							//心跳位, 0-255循环
+		unsigned char			m_response_communication_mode = 0;					//通信模式	0 = 未知, 1=自动循环模式,2=手动刷新模式
+		unsigned char			m_response_refresh_command = 0;						//刷新指令 0-255任意数字,与上一次不同即可
+		unsigned char			m_response_data_validity = 0;						//数据有效性, 0 = 未知, 1 = 有效, 2 = 无效
+
+	};
+
+	struct Ground_lidar_response_from_manager_to_plc_for_data
+	{
+		//汽车的定位信息(地面雷达)
+		float 					m_response_car_center_x = 0;				//整车的中心点x值, 四轮的中心, 单位:米 m
+		float  					m_response_car_center_y = 0;				//整车的中心点y值, 四轮的中心, 单位:米 m
+		float  					m_response_car_angle = 0;					//整车的车身旋转角, 单位:度 (-90~90)
+		float  					m_response_car_front_theta = 0;				//整车的前轮的旋转角, 单位:度 (-90~90)
+		float  					m_response_car_length = 0;					//整车的长度, 用于规避碰撞, 单位:米 m
+		float  					m_response_car_width = 0;					//整车的宽度, 用于规避碰撞, 单位:米 m
+		float  					m_response_car_height = 0;					//整车的高度, 用于规避碰撞, 单位:米 m
+		float  					m_response_car_wheel_base = 0;				//整车的轮距, 前后轮的距离, 用于机器人或agv的抓车, 单位:米 m
+		float  					m_response_car_wheel_width = 0;				//整车的轮距, 左右轮的距离, 用于机器人或agv的抓车, 单位:米 m
+		float					m_response_uniformed_car_x = 0;					//转角复位后,车辆中心点x
+		float					m_response_uniformed_car_y = 0;					//转角复位后,车辆中心点y
+		unsigned char			m_response_locate_correct = 0;				//数据是否有效, 0=无效, 1=有效
+
+		unsigned char			m_reserved45_48[3] = {0};							//预留
+		unsigned char			m_response_heartbeat = 0;							//心跳位, 0-255循环
+		unsigned char			m_response_communication_mode = 0;					//通信模式	0 = 未知, 1=自动循环模式,2=手动刷新模式
+		unsigned char			m_response_refresh_command = 0;						//刷新指令 0-255任意数字,与上一次不同即可
+		unsigned char			m_response_data_validity = 0;						//数据有效性, 0 = 未知, 1 = 有效, 2 = 无效
+	};
+
+	//plc给地面雷达
+#define GROUND_LIDAR_REQUEST_FROM_PLC_TO_MANAGER_DBNUMBER_0		9005
+#define GROUND_LIDAR_REQUEST_FROM_PLC_TO_MANAGER_DBNUMBER_1		9015
+	struct Ground_lidar_request_from_plc_to_manager
+	{
+		unsigned char			m_request_heartbeat = 0;							//心跳位, 0-255循环
+		unsigned char			m_request_communication_mode = 0;					//通信模式	0 = 未知, 1=自动循环模式,2=手动刷新模式
+		unsigned char			m_request_refresh_command = 0;						//刷新指令 0-255任意数字,与上一次不同即可
+		unsigned char			m_request_data_validity = 0;						//数据有效性, 0 = 未知, 1 = 有效, 2 = 无效
+	};
+
+
+	//防撞雷达给plc
+#define ANTICOLLISION_LIDAR_RESPONSE_FROM_MANAGER_TO_PLC_DBNUMBER_0		9006
+	struct Anticollision_lidar_response_from_manager_to_plc_for_key
+	{
+		unsigned char			m_response_heartbeat = 0;							//心跳位, 0-255循环
+		unsigned char			m_response_communication_mode = 0;					//通信模式	0 = 未知, 1=自动循环模式,2=手动刷新模式
+		unsigned char			m_response_refresh_command = 0;						//刷新指令 0-255任意数字,与上一次不同即可
+		unsigned char			m_response_data_validity = 0;						//数据有效性, 0 = 未知, 1 = 有效, 2 = 无效
+
+	};
+
+	struct Anticollision_lidar_response_from_manager_to_plc_for_data
+	{
+		unsigned char			m_response_anticollision_lidar_flag = 0;		//汽车是否停到正确的位置, 防撞雷达	预留, 楚天暂时不用,0=未知,1=位置正常,2=位置异常
+		unsigned char			m_reserved5_7[3] = {0};							//预留
+		float					m_response_offset_x = 0;						//汽车x轴的偏移量, -1.0~+1.0, 单位米
+		float					m_response_offset_angle = 0;					//汽车角度的偏移量, -7~+7, 单位度
+	};
+
+	//plc给防撞雷达
+#define ANTICOLLISION_LIDAR_REQUEST_FROM_PLC_TO_MANAGER_DBNUMBER_0		9007
+	struct Anticollision_lidar_request_from_plc_to_manager
+	{
+		unsigned char			m_request_heartbeat = 0;							//心跳位, 0-255循环
+		unsigned char			m_request_communication_mode = 0;					//通信模式	0 = 未知, 1=自动循环模式,2=手动刷新模式
+		unsigned char			m_request_refresh_command = 0;						//刷新指令 0-255任意数字,与上一次不同即可
+		unsigned char			m_request_data_validity = 0;						//数据有效性, 0 = 未知, 1 = 有效, 2 = 无效
+	};
+
+
+
+	//单片机给plc
+#define SINGLECHIP_RESPONSE_FROM_MANAGER_TO_PLC_DBNUMBER_0		9008
+#define SINGLECHIP_RESPONSE_FROM_MANAGER_TO_PLC_DBNUMBER_1		9018
+#define SINGLECHIP_RESPONSE_FROM_MANAGER_TO_PLC_DBNUMBER_2		9028
+#define SINGLECHIP_RESPONSE_FROM_MANAGER_TO_PLC_DBNUMBER_3		9038
+	struct Singlechip_response_from_manager_to_plc
+	{
+		unsigned char					m_process_status;	//流程状态
+		unsigned char					m_process_control;	//流程控制
+
+		unsigned char					m_over_border_status;							//超界状态, 0:未知, 1:正常, 2:前超界, 3:后超界, 4:左超界, 5:右超界
+		unsigned char					m_car_height_status_current;					//车高状态,当前持续的状态, 0:未知, 1:小车, 2:中车, 3:大车, 4:巨大车, 5:故障车
+		unsigned char					m_car_height_status_passing;					//车高状态,经过外门口的状态, 0:未知, 1:小车, 2:中车, 3:大车, 4:巨大车, 5:故障车
+		unsigned char					m_outside_door_status;							//外门的状态, 0:未知, 1:外门开到位, 2:外门关到位, 3:外门运行中, 4:外门故障
+		unsigned char					m_outside_door_control;							//外门的控制, 0:未知, 1:外门开, 2:外门关,
+
+		unsigned char					m_dispatch_finish_flag;			//调度完成标志位,true表示允许终端放下一辆车进入入口
+		unsigned char					m_inside_existence_flag;		//门内是否存在汽车的标志位, true表示有车
+		unsigned char					m_outside_existence_flag;		//门外是否存在汽车的标志位, 门外地感触发停车流程, true表示有车
+		unsigned char					m_reset_flag;					//重启标志, true:控制看门狗重启
+		unsigned char					m_stop_flag;					//急停标志,true:把控制口全部写0,并关闭流程。
+
+		unsigned int					m_error_code;					//错误码
+
+		unsigned char					m_reserved16_35[20] = {0};							//预留
+
+		unsigned char					m_gpio_input[16] = {0};							//gpio输入口原始数据,
+		unsigned char					m_gpio_output[8] = {0};							//gpio输出口原始数据,
+		unsigned char					m_reserved60_79[20] = {0};							//预留
+
+
+		unsigned char			m_response_heartbeat = 0;							//心跳位, 0-255循环
+		unsigned char			m_response_communication_mode = 0;					//通信模式	0 = 未知, 1=自动循环模式,2=手动刷新模式
+		unsigned char			m_response_refresh_command = 0;						//刷新指令 0-255任意数字,与上一次不同即可
+		unsigned char			m_response_data_validity = 0;						//数据有效性, 0 = 未知, 1 = 有效, 2 = 无效
+	};
+
+	//plc给单片机
+#define SINGLECHIP_REQUEST_FROM_PLC_TO_MANAGER_DBNUMBER_0		9009
+#define SINGLECHIP_REQUEST_FROM_PLC_TO_MANAGER_DBNUMBER_1		9019
+#define SINGLECHIP_REQUEST_FROM_PLC_TO_MANAGER_DBNUMBER_2		9029
+#define SINGLECHIP_REQUEST_FROM_PLC_TO_MANAGER_DBNUMBER_3		9039
+	struct Singlechip_request_from_plc_to_manager
+	{
+		unsigned char			m_request_heartbeat = 0;							//心跳位, 0-255循环
+		unsigned char			m_request_communication_mode = 0;					//通信模式	0 = 未知, 1=自动循环模式,2=手动刷新模式
+		unsigned char			m_request_refresh_command = 0;						//刷新指令 0-255任意数字,与上一次不同即可
+		unsigned char			m_request_data_validity = 0;						//数据有效性, 0 = 未知, 1 = 有效, 2 = 无效
+	};
+
+
+
+
+
+#pragma pack(pop)		//取消对齐
+
+// 子类必须把父类设定为友元函数,这样父类才能使用子类的私有构造函数。
+	friend class Singleton<Dispatch_communication>;
+private:
+	// 父类的构造函数必须保护,子类的构造函数必须私有。
+	Dispatch_communication();
+public:
+	//必须关闭拷贝构造和赋值构造,只能通过 get_instance 函数来进行操作唯一的实例。
+	Dispatch_communication(const Dispatch_communication& other) = delete;
+	Dispatch_communication& operator =(const Dispatch_communication& other) = delete;
+	~Dispatch_communication();
+public://API functions
+	//初始化 通信 模块。如下三选一
+	virtual Error_manager communication_init(int plc_id);
+	//反初始化 通信 模块。
+	virtual Error_manager communication_uninit();
+public://get or set member variable
+//	std::mutex * get_data_lock();
+//	Request_from_dispatch_to_plc * get_request_from_dispatch_to_plc();
+//	Response_from_plc_to_dispatch * get_response_from_plc_to_dispatch();
+//	Status_from_dispatch_to_plc * get_status_from_dispatch_to_plc();
+//	Status_from_plc_to_dispatch * get_status_from_plc_to_dispatch();
+protected://member functions
+	//更新数据
+	virtual Error_manager updata_receive_buf();
+	virtual Error_manager updata_send_buf();
+
+protected://member variable
+public:
+
+	int											m_plc_id;		//plc的id, 楚天车库的单元号
+
+	std::mutex									m_data_lock;						//数据锁
+
+	Catcher_request_from_dispatch_to_plc_for_data		m_catcher_request_from_dispatch_to_plc_for_data[2];	//抓车模块给plc发送请求消息的指令结构体
+	Catcher_request_from_dispatch_to_plc_for_key		m_catcher_request_from_dispatch_to_plc_for_key[2];	//抓车模块给plc发送请求消息的指令结构体
+	Catcher_response_from_plc_to_dispatch				m_catcher_response_from_plc_to_dispatch[2];	//plc给抓车模块发送答复消息的指令结构体
+	Catcher_status_from_plc_to_dispatch					m_catcher_status_from_plc_to_dispatch[2];	//plc给抓车模块发送状态消息的指令结构体
+
+	Carrier_request_from_dispatch_to_plc_for_data		m_carrier_request_from_dispatch_to_plc_for_data[3];	//搬运器给plc发送请求消息的指令结构体
+	Carrier_request_from_dispatch_to_plc_for_key		m_carrier_request_from_dispatch_to_plc_for_key[3];	//搬运器给plc发送请求消息的指令结构体
+	Carrier_response_from_plc_to_dispatch				m_carrier_response_from_plc_to_dispatch[3];	//plc给搬运器发送答复消息的指令结构体
+	Carrier_status_from_plc_to_dispatch					m_carrier_status_from_plc_to_dispatch[3];	//plc给搬运器发送状态消息的指令结构体
+
+	Passageway_request_from_dispatch_to_plc_for_data	m_passageway_request_from_dispatch_to_plc_for_data[8];	//通道口给plc发送请求消息的指令结构体
+	Passageway_request_from_dispatch_to_plc_for_key		m_passageway_request_from_dispatch_to_plc_for_key[8];	//通道口给plc发送请求消息的指令结构体
+	Passageway_response_from_plc_to_dispatch			m_passageway_response_from_plc_to_dispatch[8];	//plc给通道口发送答复消息的指令结构体
+	Passageway_status_from_plc_to_dispatch				m_passageway_status_from_plc_to_dispatch[8];	//plc给通道口发送状态消息的指令结构体
+
+
+	//调度指令
+	Dispatch_request_from_manager_to_plc_for_data				m_dispatch_request_from_manager_to_plc_for_data;
+	Dispatch_request_from_manager_to_plc_for_key				m_dispatch_request_from_manager_to_plc_for_key;
+	Dispatch_response_from_plc_to_manager						m_dispatch_response_from_plc_to_manager;
+	//调度状态
+	Dispatch_plc_status_from_manager_to_plc						m_dispatch_plc_status_from_manager_to_plc;
+	Dispatch_plc_status_from_plc_to_manager						m_dispatch_plc_status_from_plc_to_manager;
+
+	//地面雷达指令
+	Ground_lidar_response_from_manager_to_plc_for_data			m_ground_lidar_response_from_manager_to_plc_for_data[2];
+	Ground_lidar_response_from_manager_to_plc_for_key			m_ground_lidar_response_from_manager_to_plc_for_key[2];
+	Ground_lidar_request_from_plc_to_manager					m_ground_lidar_request_from_plc_to_manager[2];
+
+	//防撞雷达指令
+	Anticollision_lidar_response_from_manager_to_plc_for_data	m_anticollision_lidar_response_from_manager_to_plc_for_data;
+	Anticollision_lidar_response_from_manager_to_plc_for_key	m_anticollision_lidar_response_from_manager_to_plc_for_key;
+	Anticollision_lidar_request_from_plc_to_manager				m_anticollision_lidar_request_from_plc_to_manager;
+
+	//单片机
+	Singlechip_response_from_manager_to_plc					m_singlechip_response_from_manager_to_plc[4];
+	Singlechip_request_from_plc_to_manager					m_singlechip_request_from_plc_to_manager[4];
+private:
+
+};
+
+
+#endif //NNXX_TESTS_DISPATCH_COMMUNICATION_H

+ 629 - 0
plc调度节点/dispatch/dispatch_coordinates.cpp

@@ -0,0 +1,629 @@
+//
+// Created by huli on 2021/3/24.
+//
+
+#include "dispatch_coordinates.h"
+#include "../tool/proto_tool.h"
+
+
+Dispatch_coordinates::Dispatch_coordinates()
+{
+	mpp_space_lock = nullptr;
+	m_space_lock_rows = 0;
+	m_space_lock_columns = 0;
+	m_space_lock_total = 0;
+
+}
+Dispatch_coordinates::~Dispatch_coordinates()
+{
+	dispatch_coordinates_uninit();
+}
+
+//初始化 调度的坐标系 模块。如下三选一
+Error_manager Dispatch_coordinates::dispatch_coordinates_init()
+{
+	return  dispatch_coordinates_init_from_protobuf(DISPATCH_COORDINATES_PARAMETER_PATH);
+}
+
+//初始化 调度的坐标系 模块。从文件读取
+Error_manager Dispatch_coordinates::dispatch_coordinates_init_from_protobuf(std::string prototxt_path)
+{
+	Dispatch_proto::Dispatch_coordinates_parameter_all t_dispatch_coordinates_parameter_all;
+	if(!  proto_tool::read_proto_param(prototxt_path,t_dispatch_coordinates_parameter_all) )
+	{
+		return Error_manager(DISPATCH_COORDINATES_READ_PROTOBUF_ERROR,MINOR_ERROR,
+							 "Dispatch_coordinates read_proto_param  failed");
+	}
+
+	return dispatch_coordinates_init_from_protobuf(t_dispatch_coordinates_parameter_all);
+}
+
+//初始化 调度的坐标系 模块。从protobuf读取
+Error_manager Dispatch_coordinates::dispatch_coordinates_init_from_protobuf(Dispatch_proto::Dispatch_coordinates_parameter_all& dispatch_coordinates_parameter_all)
+{
+	LOG(INFO) << " ---Dispatch_coordinates::dispatch_coordinates_init_from_protobuf() run--- "<< this;
+	Error_manager t_error;
+
+	m_space_lock_rows = dispatch_coordinates_parameter_all.parkspace_number().rows();
+	m_space_lock_columns = dispatch_coordinates_parameter_all.parkspace_number().columns();
+	m_space_lock_total = dispatch_coordinates_parameter_all.parkspace_number().total();
+	m_liftway_width = dispatch_coordinates_parameter_all.parkspace_number().liftway_width();
+
+	mpp_space_lock = new space_device*[m_space_lock_rows];
+	for (int i = 0; i < m_space_lock_rows; ++i)
+	{
+		mpp_space_lock[i] = new space_device[m_space_lock_columns];
+		for (int j = 0; j < m_space_lock_columns; ++j)
+		{
+			//注意了, 这里一定要初始化为-1, 因为设备id=0 是有效设备
+			mpp_space_lock[i][j].m_catcher_id = -1;
+			mpp_space_lock[i][j].m_carrier_id = -1;
+		}
+	}
+
+
+
+	int size;
+	size = dispatch_coordinates_parameter_all.packspace_coordinates_parameters_size();
+	for (int i = 0; i < size; ++i)
+	{
+		Point3D_tool::Point3D t_point3d;
+		int id = dispatch_coordinates_parameter_all.packspace_coordinates_parameters(i).id();
+		t_point3d.x = dispatch_coordinates_parameter_all.packspace_coordinates_parameters(i).x();
+		t_point3d.y = dispatch_coordinates_parameter_all.packspace_coordinates_parameters(i).y();
+		t_point3d.z = dispatch_coordinates_parameter_all.packspace_coordinates_parameters(i).z();
+		m_packspace_coordinates_map[id] = t_point3d;
+	}
+
+	size = dispatch_coordinates_parameter_all.passageway_coordinates_parameters_size();
+	for (int i = 0; i < size; ++i)
+	{
+		Point3D_tool::Point3D t_point3d;
+		int id = dispatch_coordinates_parameter_all.passageway_coordinates_parameters(i).id();
+		t_point3d.x = dispatch_coordinates_parameter_all.passageway_coordinates_parameters(i).x();
+		t_point3d.y = dispatch_coordinates_parameter_all.passageway_coordinates_parameters(i).y();
+		t_point3d.z = dispatch_coordinates_parameter_all.passageway_coordinates_parameters(i).z();
+		m_passageway_coordinates_map[id] = t_point3d;
+	}
+
+	size = dispatch_coordinates_parameter_all.carrier_coordinates_parameters_size();
+	for (int i = 0; i < size; ++i)
+	{
+		Point3D_tool::Point3D t_point3d;
+		int id = dispatch_coordinates_parameter_all.carrier_coordinates_parameters(i).id();
+		t_point3d.x = dispatch_coordinates_parameter_all.carrier_coordinates_parameters(i).x();
+		t_point3d.y = dispatch_coordinates_parameter_all.carrier_coordinates_parameters(i).y();
+		t_point3d.z = dispatch_coordinates_parameter_all.carrier_coordinates_parameters(i).z();
+		m_carrier_coordinates_map[id] = t_point3d;
+	}
+
+	size = dispatch_coordinates_parameter_all.catcher_coordinates_parameters_size();
+	for (int i = 0; i < size; ++i)
+	{
+		Point3D_tool::Point3D t_point3d;
+		int id = dispatch_coordinates_parameter_all.catcher_coordinates_parameters(i).id();
+		t_point3d.x = dispatch_coordinates_parameter_all.catcher_coordinates_parameters(i).x();
+		t_point3d.y = dispatch_coordinates_parameter_all.catcher_coordinates_parameters(i).y();
+		t_point3d.z = dispatch_coordinates_parameter_all.catcher_coordinates_parameters(i).z();
+		m_catcher_coordinates_map[id] = t_point3d;
+	}
+
+
+	m_carrier_box.x_min = dispatch_coordinates_parameter_all.carrier_box_parameters().x_min();
+	m_carrier_box.x_max = dispatch_coordinates_parameter_all.carrier_box_parameters().x_max();
+	m_carrier_box.y_min = dispatch_coordinates_parameter_all.carrier_box_parameters().y_min();
+	m_carrier_box.y_max = dispatch_coordinates_parameter_all.carrier_box_parameters().y_max();
+	m_carrier_box.z_min = dispatch_coordinates_parameter_all.carrier_box_parameters().z_min();
+	m_carrier_box.z_max = dispatch_coordinates_parameter_all.carrier_box_parameters().z_max();
+
+	m_catcher_box.x_min = dispatch_coordinates_parameter_all.catcher_box_parameters().x_min();
+	m_catcher_box.x_max = dispatch_coordinates_parameter_all.catcher_box_parameters().x_max();
+	m_catcher_box.y_min = dispatch_coordinates_parameter_all.catcher_box_parameters().y_min();
+	m_catcher_box.y_max = dispatch_coordinates_parameter_all.catcher_box_parameters().y_max();
+	m_catcher_box.z_min = dispatch_coordinates_parameter_all.catcher_box_parameters().z_min();
+	m_catcher_box.z_max = dispatch_coordinates_parameter_all.catcher_box_parameters().z_max();
+
+	m_catcher_b_min = dispatch_coordinates_parameter_all.catcher_b_min();
+	m_catcher_b_max = dispatch_coordinates_parameter_all.catcher_b_max();
+	m_catcher_d1_min = dispatch_coordinates_parameter_all.catcher_d1_min();
+	m_catcher_d1_max = dispatch_coordinates_parameter_all.catcher_d1_max();
+	m_catcher_d2_min = dispatch_coordinates_parameter_all.catcher_d2_min();
+	m_catcher_d2_max = dispatch_coordinates_parameter_all.catcher_d2_max();
+
+	std::cout << " huli test :::: " << " m_packspace_coordinates_map.size() = " << m_packspace_coordinates_map.size() << std::endl;
+	std::cout << " huli test :::: " << " m_passageway_coordinates_map.size() = " << m_passageway_coordinates_map.size() << std::endl;
+	std::cout << " huli test :::: " << " m_carrier_coordinates_map.size() = " << m_carrier_coordinates_map.size() << std::endl;
+	std::cout << " huli test :::: " << " m_catcher_coordinates_map.size() = " << m_catcher_coordinates_map.size() << std::endl;
+
+	m_default_wheelbase = dispatch_coordinates_parameter_all.default_wheelbase();
+
+	m_catcher_1th_floor_z = dispatch_coordinates_parameter_all.catcher_1th_floor_z();
+	m_catcher_2th_floor_z = dispatch_coordinates_parameter_all.catcher_2th_floor_z();
+	m_catcher_3th_floor_z = dispatch_coordinates_parameter_all.catcher_3th_floor_z();
+	m_catcher_4th_floor_z = dispatch_coordinates_parameter_all.catcher_4th_floor_z();
+
+	m_carrier_1th_floor_z = dispatch_coordinates_parameter_all.carrier_1th_floor_z();
+	m_carrier_2th_floor_z = dispatch_coordinates_parameter_all.carrier_2th_floor_z();
+	m_carrier_3th_floor_z = dispatch_coordinates_parameter_all.carrier_3th_floor_z();
+	m_carrier_4th_floor_z = dispatch_coordinates_parameter_all.carrier_4th_floor_z();
+
+	m_catcher_d1_d2_distance = dispatch_coordinates_parameter_all.catcher_d1_d2_distance();
+	m_catcher_wheel_base_limit = dispatch_coordinates_parameter_all.catcher_wheel_base_limit();
+
+	m_carrier_y_y1_distance = dispatch_coordinates_parameter_all.carrier_y_y1_distance();
+	m_carrier_default_y1_back = dispatch_coordinates_parameter_all.carrier_default_y1_back();
+	m_carrier_default_y1_leave = dispatch_coordinates_parameter_all.carrier_default_y1_leave();
+	m_carrier_default_y_back = dispatch_coordinates_parameter_all.carrier_default_y_back();
+	m_carrier_default_y_leave = dispatch_coordinates_parameter_all.carrier_default_y_leave();
+
+	m_carrier_default_x_left = dispatch_coordinates_parameter_all.carrier_default_x_left();
+	m_carrier_default_x_right = dispatch_coordinates_parameter_all.carrier_default_x_right();
+
+	m_passageway_terminal_id_min = dispatch_coordinates_parameter_all.passageway_terminal_id_min();
+	m_passageway_terminal_id_max = dispatch_coordinates_parameter_all.passageway_terminal_id_max();
+	m_passageway_terminal_number = dispatch_coordinates_parameter_all.passageway_terminal_number();
+	size = dispatch_coordinates_parameter_all.passageway_functioning_patterns_size();
+	for (int i = m_passageway_terminal_id_min; i < size; ++i)
+	{
+		m_passageway_functioning_pattern_map[i] = (Passageway_functioning_pattern)dispatch_coordinates_parameter_all.passageway_functioning_patterns(i);
+	}
+	if ( m_passageway_terminal_number != m_passageway_terminal_id_max - m_passageway_terminal_id_min +1 ||
+		 m_passageway_terminal_number != size)
+	{
+		return Error_manager(Error_code::PARAMETER_ERROR, Error_level::MINOR_ERROR,
+							 " Dispatch_coordinates::dispatch_coordinates_init_from_protobuf PARAMRTER ERROR ");
+	}
+
+	m_parkspace_id_min = dispatch_coordinates_parameter_all.parkspace_id_min();
+	m_parkspace_id_max = dispatch_coordinates_parameter_all.parkspace_id_max();
+	m_parkspace_id_total = dispatch_coordinates_parameter_all.parkspace_id_total();
+
+	m_third_floor_parkspace_id_min = dispatch_coordinates_parameter_all.third_floor_parkspace_id_min();
+	m_third_floor_parkspace_id_max = dispatch_coordinates_parameter_all.third_floor_parkspace_id_max();
+	m_third_floor_parkspace_id_total = dispatch_coordinates_parameter_all.third_floor_parkspace_id_total();
+
+	m_car_wheel_base_min = dispatch_coordinates_parameter_all.car_wheel_base_min();
+	m_car_wheel_base_max = dispatch_coordinates_parameter_all.car_wheel_base_max();
+
+	m_separated_distance_z = dispatch_coordinates_parameter_all.m_separated_distance_z();
+	m_separated_distance_x = dispatch_coordinates_parameter_all.m_separated_distance_x();
+
+	return Error_code::SUCCESS;
+}
+//反初始化
+Error_manager Dispatch_coordinates::dispatch_coordinates_uninit()
+{
+	for (int i = 0; i < m_space_lock_rows; ++i)
+	{
+		delete [](mpp_space_lock[i]);
+	}
+	delete [](mpp_space_lock);
+	return Error_code::SUCCESS;
+}
+
+//获取2点之间的路径长度, 只算x轴和z轴, 只是计算一个大概值
+Error_manager Dispatch_coordinates::get_distance(int coordinates_id_1, int coordinates_id_2, Parkspace_path parkspace_path, float & distance)
+{
+	//是否在1楼的标记位,
+	float t_distance_x = 0;
+	float t_distance_z = 0;
+
+	//检查合法性
+	if ( m_carrier_coordinates_map.find(coordinates_id_1) != m_carrier_coordinates_map.end() &&
+		 m_carrier_coordinates_map.find(coordinates_id_2) != m_carrier_coordinates_map.end() )
+	{
+		//计算距离
+		if(coordinates_id_1 == coordinates_id_2)
+		{
+			distance = 0;
+		}
+		else if ( m_carrier_coordinates_map[coordinates_id_1].z == m_carrier_coordinates_map[coordinates_id_2].z )
+		{
+			distance = m_carrier_coordinates_map[coordinates_id_1].x - m_carrier_coordinates_map[coordinates_id_2].x;
+			if ( distance<0 )
+			{
+				distance = -distance;
+			}
+		}
+		else if ( parkspace_path == Dispatch_coordinates::Parkspace_path::LEFT_PATH )
+		{
+			t_distance_x = (m_carrier_coordinates_map[coordinates_id_1].x - m_carrier_default_x_left) +
+						   (m_carrier_coordinates_map[coordinates_id_2].x - m_carrier_default_x_left);
+			t_distance_z = m_carrier_coordinates_map[coordinates_id_1].z - m_carrier_coordinates_map[coordinates_id_2].z;
+			if ( t_distance_z<0 )
+			{
+				t_distance_z = -t_distance_z;
+			}
+			distance = t_distance_x + t_distance_z;
+		}
+		else if ( parkspace_path == Dispatch_coordinates::Parkspace_path::RIGHT_PATH )
+		{
+			t_distance_x = (m_carrier_default_x_right - m_carrier_coordinates_map[coordinates_id_1].x ) +
+						   (m_carrier_default_x_right - m_carrier_coordinates_map[coordinates_id_2].x );
+			t_distance_z = m_carrier_coordinates_map[coordinates_id_1].z - m_carrier_coordinates_map[coordinates_id_2].z;
+			if ( t_distance_z<0 )
+			{
+				t_distance_z = -t_distance_z;
+			}
+			distance = t_distance_x + t_distance_z;
+		}
+		else if ( parkspace_path == Dispatch_coordinates::Parkspace_path::TEMPORARY_CACHE_PATH )
+		{
+			t_distance_x = m_carrier_coordinates_map[coordinates_id_1].x - m_carrier_coordinates_map[coordinates_id_2].x;
+			if ( t_distance_x<0 )
+			{
+				t_distance_x = -t_distance_x;
+			}
+			t_distance_z = m_carrier_coordinates_map[coordinates_id_1].z - m_carrier_coordinates_map[coordinates_id_2].z;
+			if ( t_distance_z<0 )
+			{
+				t_distance_z = -t_distance_z;
+			}
+			distance = t_distance_x + t_distance_z;
+		}
+		else
+		{
+			return Error_manager(Error_code::DISPATCH_COORDINATES_PATH_ERROR, Error_level::MINOR_ERROR,
+								 " Dispatch_coordinates::get_distance parkspace_path error ");
+		}
+	}
+	else
+	{
+		return Error_manager(Error_code::DISPATCH_COORDINATES_ID_ERROR, Error_level::MINOR_ERROR,
+							 " Dispatch_coordinates::get_distance coordinates_id error ");
+	}
+	return Error_code::SUCCESS;
+}
+
+//把1楼出入口的坐标修正到2楼.
+bool Dispatch_coordinates::amend_coordinates_from_1st_floor_to_2nd_floor(int & coordinates_id)
+{
+	if ( coordinates_id >= PASSAGEWAY_ID_BASE+1 && coordinates_id<= PASSAGEWAY_ID_BASE + m_passageway_terminal_id_max-1)
+	{
+		coordinates_id = coordinates_id+100;	//例如:把 1103 改为 1203
+		return true;
+	}
+	else
+	{
+		return false;
+	}
+	return false;
+}
+
+//选择最近的搬运器, return true:选左边, return false:选右边
+bool Dispatch_coordinates::choice_nearest_carrier(int dispatch_source, int coordinates_id_1, int coordinates_id_2)
+{
+	Error_manager t_error;
+	//选最近的搬运器
+	float t_distance_left = 0;
+	t_error = get_distance(dispatch_source, coordinates_id_1, Dispatch_coordinates::Parkspace_path::LEFT_PATH, t_distance_left );
+	if ( t_error != Error_code::SUCCESS )
+	{
+		LOG(INFO) << " Dispatch_manager::resource_allocation() m_process_pickup_list error = "<< t_error.to_string() << "   " << this;
+	}
+	float t_distance_right = 0;
+	t_error = get_distance(dispatch_source, coordinates_id_2, Dispatch_coordinates::Parkspace_path::RIGHT_PATH, t_distance_right );
+	if ( t_error != Error_code::SUCCESS )
+	{
+		LOG(INFO) << " Dispatch_manager::resource_allocation() m_process_pickup_list error = "<< t_error.to_string() << "   " << this;
+	}
+	if ( t_distance_left <= t_distance_right )
+	{
+		return true;
+	}
+	else
+	{
+		return false;
+	}
+}
+
+//判断取车的路径
+Dispatch_coordinates::Parkspace_path Dispatch_coordinates::get_pickup_path(int dispatch_source, int dispatch_destination)
+{
+	if ( dispatch_source >= 1 && dispatch_source <= 165 &&
+		 dispatch_destination >= 1100 && dispatch_destination <= 1107)
+	{
+		if ( dispatch_source >= 19 && dispatch_source <= 27 )
+		{
+			if ( dispatch_destination >= 1101 && dispatch_destination <= 1106 )
+			{
+				return Dispatch_coordinates::Parkspace_path::THIRD_FLOOR_PATH;
+			}
+			else
+			{
+				return Dispatch_coordinates::Parkspace_path::UNKNOW_PATH;
+			}
+		}
+		else
+		{
+			int t_columns = dispatch_source % 15;
+			if ( (t_columns ==1 || t_columns == 2 || t_columns ==3) ||
+				 (dispatch_source >= 34 && dispatch_source <= 37) )
+			{
+				if ( dispatch_destination >= 1100 && dispatch_destination <= 1106 )
+				{
+					return Dispatch_coordinates::Parkspace_path::LEFT_PATH;
+				}
+				else
+				{
+					return Dispatch_coordinates::Parkspace_path::UNKNOW_PATH;
+				}
+			}
+			else if ( (t_columns ==13 || t_columns == 14 || t_columns ==0) ||
+					  (dispatch_source >= 38 && dispatch_source <= 42) )
+			{
+				if ( dispatch_destination >= 1101 && dispatch_destination <= 1107 )
+				{
+					return Dispatch_coordinates::Parkspace_path::RIGHT_PATH;
+				}
+				else
+				{
+					return Dispatch_coordinates::Parkspace_path::UNKNOW_PATH;
+				}
+			}
+			else
+			{
+				if ( dispatch_destination >= 1101 && dispatch_destination <= 1106 )
+				{
+					return Dispatch_coordinates::Parkspace_path::DOUBLE_PATH;
+				}
+				else if ( dispatch_destination == 1100 )
+				{
+					return Dispatch_coordinates::Parkspace_path::LEFT_PATH;
+				}
+				else if ( dispatch_destination == 1107 )
+				{
+					return Dispatch_coordinates::Parkspace_path::RIGHT_PATH;
+				}
+				else
+				{
+					return Dispatch_coordinates::Parkspace_path::UNKNOW_PATH;
+				}
+			}
+		}
+	}
+	else
+	{
+		return Dispatch_coordinates::Parkspace_path::UNKNOW_PATH;
+	}
+
+	return Dispatch_coordinates::Parkspace_path::UNKNOW_PATH;
+}
+
+
+//检查停车位和取车位, 判断是否能改道
+bool Dispatch_coordinates::is_able_redirect(int pickup_parkspace_id, int store_parkspace_id)
+{
+	return true;
+}
+
+//搬运器尝试空间加锁
+Error_manager Dispatch_coordinates::carrier_try_space_lock(int row_min, int column_min, int row_max, int column_max, int carrier_id, int& avoid_catcher_id )
+{
+	std::unique_lock<std::mutex> t_lock(m_lock);
+	bool try_flag = true;
+	avoid_catcher_id = -1;
+	for (int i = row_min; i <= row_max; ++i)
+	{
+		for (int j = column_min; j <= column_max ; ++j)
+		{
+			if ( mpp_space_lock[i][j].m_carrier_id != -1 &&
+				 mpp_space_lock[i][j].m_carrier_id != carrier_id )
+			{
+				try_flag = false;
+				break;
+			}
+			if ( mpp_space_lock[i][j].m_catcher_id != -1 )
+			{
+				try_flag = false;
+				avoid_catcher_id = mpp_space_lock[i][j].m_catcher_id;
+				break;
+			}
+		}
+	}
+
+	if ( try_flag )
+	{
+		for (int i = row_min; i <= row_max; ++i)
+		{
+			for (int j = column_min; j <= column_max ; ++j)
+			{
+				mpp_space_lock[i][j].m_carrier_id = carrier_id;
+			}
+		}
+		return Error_code::SUCCESS;
+	}
+	else
+	{
+		return Error_manager(Error_code::DISPATCH_COORDINATES_CAN_NOT_LOCK, Error_level::MINOR_ERROR,
+							 " Dispatch_coordinates::carrier_try_space_lock error ");
+	}
+}
+//抓取器尝试空间加锁
+Error_manager Dispatch_coordinates::catcher_try_space_lock(int row_min, int column_min, int row_max, int column_max, int catcher_id )
+{
+	std::unique_lock<std::mutex> t_lock(m_lock);
+	bool try_flag = true;
+	for (int i = row_min; i <= row_max; ++i)
+	{
+		for (int j = column_min; j <= column_max ; ++j)
+		{
+			if ( (mpp_space_lock[i][j].m_catcher_id != -1 && mpp_space_lock[i][j].m_catcher_id != catcher_id)
+				 || mpp_space_lock[i][j].m_carrier_id != -1)
+			{
+				try_flag = false;
+				break;
+			}
+		}
+	}
+
+	if ( try_flag )
+	{
+		for (int i = row_min; i <= row_max; ++i)
+		{
+			for (int j = column_min; j <= column_max ; ++j)
+			{
+				mpp_space_lock[i][j].m_catcher_id = catcher_id;
+			}
+		}
+		return Error_code::SUCCESS;
+	}
+	else
+	{
+		return Error_manager(Error_code::DISPATCH_COORDINATES_CAN_NOT_LOCK, Error_level::MINOR_ERROR,
+							 " Dispatch_coordinates::catcher_try_space_lock error ");
+	}
+}
+//搬运器强制空间加锁(不做判断了, 直接加锁)
+Error_manager Dispatch_coordinates::carrier_force_space_lock(int row_min, int column_min, int row_max, int column_max, int carrier_id )
+{
+	//不做判断了, 直接加锁
+	std::unique_lock<std::mutex> t_lock(m_lock);
+	for (int i = row_min; i <= row_max; ++i)
+	{
+		for (int j = column_min; j <= column_max ; ++j)
+		{
+			mpp_space_lock[i][j].m_carrier_id = carrier_id;
+		}
+	}
+	return Error_code::SUCCESS;
+}
+//抓取器强制空间加锁(不做判断了, 直接加锁)
+Error_manager Dispatch_coordinates::catcher_force_space_lock(int row_min, int column_min, int row_max, int column_max, int catcher_id )
+{
+	//不做判断了, 直接加锁
+	std::unique_lock<std::mutex> t_lock(m_lock);
+	for (int i = row_min; i <= row_max; ++i)
+	{
+		for (int j = column_min; j <= column_max ; ++j)
+		{
+			mpp_space_lock[i][j].m_catcher_id = catcher_id;
+		}
+	}
+	return Error_code::SUCCESS;
+}
+//搬运器解锁, 退回电梯井, 全部解锁
+Error_manager Dispatch_coordinates::carrier_space_unlock(int carrier_id)
+{
+	std::unique_lock<std::mutex> t_lock(m_lock);
+	for (int i = 0; i < m_space_lock_rows; ++i)
+	{
+		for (int j = 0; j < m_space_lock_columns ; ++j)
+		{
+			if ( mpp_space_lock[i][j].m_carrier_id == carrier_id )
+			{
+				mpp_space_lock[i][j].m_carrier_id = -1;
+			}
+		}
+	}
+	return Error_code::SUCCESS;
+}
+//抓取器解锁, 上升到最上层, 全部解锁, 保留4楼的空间锁
+Error_manager Dispatch_coordinates::catcher_space_unlock(int catcher_coordinates_id, int catcher_id)
+{
+	std::unique_lock<std::mutex> t_lock(m_lock);
+	for (int i = 0; i < m_space_lock_rows; ++i)
+	{
+		for (int j = 0; j < m_space_lock_columns ; ++j)
+		{
+			if ( mpp_space_lock[i][j].m_catcher_id == catcher_id )
+			{
+				mpp_space_lock[i][j].m_catcher_id = -1;
+			}
+		}
+	}
+	//保留4楼的空间锁
+	if ( catcher_coordinates_id >= 34 && catcher_coordinates_id <= 42 )
+	{
+		int t_coordinates_columns = catcher_coordinates_id -30-1;
+		catcher_3rd_4st_floor_space_lock(t_coordinates_columns, catcher_id);
+	}
+	else if ( catcher_coordinates_id >= 1401 && catcher_coordinates_id <= 1406 )
+	{
+		int t_coordinates_columns = catcher_coordinates_id - 1400;
+		int temp = (t_coordinates_columns-1)%2;
+		t_coordinates_columns = 4 + ((t_coordinates_columns-1)/2)*3 + temp*2 -1;
+		catcher_3rd_4st_floor_space_lock(t_coordinates_columns, catcher_id);
+	}
+	else
+	{
+		return Error_manager(Error_code::DISPATCH_COORDINATES_ID_ERROR, Error_level::MINOR_ERROR,
+							 " Dispatch_coordinates::catcher_space_unlock error ");
+	}
+	return Error_code::SUCCESS;
+}
+//抓取器 加锁3楼和4楼的2*3个车位
+Error_manager Dispatch_coordinates::catcher_3rd_4st_floor_space_lock(int catcher_4st_floor_coordinates_columns, int catcher_id)
+{
+	//周围2*3个车位 加锁
+	mpp_space_lock[1][catcher_4st_floor_coordinates_columns-1].m_catcher_id = catcher_id;
+	mpp_space_lock[1][catcher_4st_floor_coordinates_columns].m_catcher_id = catcher_id;
+	mpp_space_lock[1][catcher_4st_floor_coordinates_columns+1].m_catcher_id = catcher_id;
+	mpp_space_lock[2][catcher_4st_floor_coordinates_columns-1].m_catcher_id = catcher_id;
+	mpp_space_lock[2][catcher_4st_floor_coordinates_columns].m_catcher_id = catcher_id;
+	mpp_space_lock[2][catcher_4st_floor_coordinates_columns+1].m_catcher_id = catcher_id;
+	return Error_code::SUCCESS;
+}
+
+void Dispatch_coordinates::set_space_lock(int space_rows, int space_columns, int catcher_id, int carrier_id)
+{
+	std::unique_lock<std::mutex> t_lock(m_lock);
+	mpp_space_lock[space_rows][space_columns].m_catcher_id = catcher_id;
+	mpp_space_lock[space_rows][space_columns].m_carrier_id = carrier_id;
+}
+void Dispatch_coordinates::set_space_lock_for_catcher(int space_rows, int space_columns, int catcher_id)
+{
+	std::unique_lock<std::mutex> t_lock(m_lock);
+	mpp_space_lock[space_rows][space_columns].m_catcher_id = catcher_id;
+}
+void Dispatch_coordinates::set_space_lock_for_carrier(int space_rows, int space_columns, int carrier_id)
+{
+	std::unique_lock<std::mutex> t_lock(m_lock);
+	mpp_space_lock[space_rows][space_columns].m_carrier_id = carrier_id;
+}
+void Dispatch_coordinates::set_space_lock(int space_id, int catcher_id, int carrier_id)
+{
+	int space_rows = (space_id-1) / m_space_lock_columns;
+	int space_columns = (space_id-1) % m_space_lock_columns;
+	set_space_lock(space_rows, space_columns, catcher_id, carrier_id);
+}
+void Dispatch_coordinates::set_space_lock_for_catcher(int space_id, int catcher_id)
+{
+	int space_rows = (space_id-1) / m_space_lock_columns;
+	int space_columns = (space_id-1) % m_space_lock_columns;
+	set_space_lock_for_catcher(space_rows, space_columns, catcher_id);
+}
+void Dispatch_coordinates::set_space_lock_for_carrier(int space_id, int carrier_id)
+{
+	int space_rows = (space_id-1) / m_space_lock_columns;
+	int space_columns = (space_id-1) % m_space_lock_columns;
+	set_space_lock_for_carrier(space_rows, space_columns, carrier_id);
+}
+void Dispatch_coordinates::cout_space_lock()
+{
+	std::unique_lock<std::mutex> t_lock(m_lock);
+	std::cout << " huli test :::: " << " Dispatch_coordinates::cout_space_lock() = " << "mpp_space_lock" << std::endl;
+	for (int i = m_space_lock_rows-1; i >=0; --i)
+	{
+		for (int j = m_space_lock_columns-1; j >=0  ; --j)
+		{
+			if ( mpp_space_lock[i][j].m_carrier_id == -1 )
+			{
+				printf("( _");
+			}
+			else
+			{
+				printf("(%d_", mpp_space_lock[i][j].m_carrier_id);
+			}
+			if ( mpp_space_lock[i][j].m_catcher_id == -1 )
+			{
+				printf(" )    ");
+			}
+			else
+			{
+				printf("%d)    ", mpp_space_lock[i][j].m_catcher_id);
+			}
+		}
+		std::cout << std::endl;
+	}
+}

+ 199 - 0
plc调度节点/dispatch/dispatch_coordinates.h

@@ -0,0 +1,199 @@
+//
+// Created by huli on 2021/3/24.
+//
+
+#ifndef NNXX_TESTS_DISPATCH_COORDINATES_H
+#define NNXX_TESTS_DISPATCH_COORDINATES_H
+
+#include "../error_code/error_code.h"
+#include "../dispatch/dispatch_parameter.pb.h"
+#include "../tool/singleton.h"
+#include "../tool/point3D_tool.h"
+#include "../tool/common_data.h"
+#include <glog/logging.h>
+#include <map>
+#include <mutex>
+
+//调度的坐标系
+class Dispatch_coordinates:public Singleton<Dispatch_coordinates>
+{
+// 子类必须把父类设定为友元函数,这样父类才能使用子类的私有构造函数。
+	friend class Singleton<Dispatch_coordinates>;
+
+public:
+	//调度坐标参数
+#define DISPATCH_COORDINATES_PARAMETER_PATH "../setting/dispatch_coordinates.prototxt"
+
+	//出入口的功能模式
+	enum Passageway_functioning_pattern
+	{
+		PASSAGEWAY_FUNCTIONING_PATTERN_UNKNOWN          = 0,    //未知
+		PASSAGEWAY_FUNCTIONING_PATTERN_INLET            = 1,    //单向入口
+		PASSAGEWAY_FUNCTIONING_PATTERN_OUTLET           = 2,    //单向出口
+		PASSAGEWAY_FUNCTIONING_PATTERN_BIDIRECTION      = 3,    //双向口
+	};
+
+	//车位分配路线(根据中跑车的路线来定)
+	enum Parkspace_path
+	{
+		UNKNOW_PATH = 0,				//未知
+		OPTIMAL_PATH = 1,				//最优路径, A方案
+		LEFT_PATH = 2,					//左侧路径, B方案
+		RIGHT_PATH = 3,					//右车路径, B方案
+		TEMPORARY_CACHE_PATH = 4,		//临时停车位路径, B方案
+
+		DOUBLE_PATH = 5, 				//左右都可以的路径, B方案取车专用
+		THIRD_FLOOR_PATH = 6, 			//3楼路径, B方案取车专用
+
+	};
+
+	//调度设备的id集合
+	struct space_device
+	{
+		int m_catcher_id;
+		int m_carrier_id;
+	};
+
+private:
+	// 父类的构造函数必须保护,子类的构造函数必须私有。
+	Dispatch_coordinates();
+public:
+	//必须关闭拷贝构造和赋值构造,只能通过 get_instance 函数来进行操作唯一的实例。
+	Dispatch_coordinates(const Dispatch_coordinates& other) = delete;
+	Dispatch_coordinates& operator =(const Dispatch_coordinates& other) = delete;
+	~Dispatch_coordinates();
+public://API functions
+	//初始化 调度的坐标系 模块。如下三选一
+	virtual Error_manager dispatch_coordinates_init();
+	//初始化 调度的坐标系 模块。从文件读取
+	Error_manager dispatch_coordinates_init_from_protobuf(std::string prototxt_path);
+	//初始化 调度的坐标系 模块。从protobuf读取
+	Error_manager dispatch_coordinates_init_from_protobuf(Dispatch_proto::Dispatch_coordinates_parameter_all& dispatch_coordinates_parameter_all);
+	//反初始化
+	virtual Error_manager dispatch_coordinates_uninit();
+	//获取2点之间的路径长度, 只算x轴和z轴, 只是计算一个大概值
+	Error_manager get_distance(int coordinates_id_1, int coordinates_id_2, Parkspace_path parkspace_path, float & distance);
+	//把1楼出入口的坐标修正到2楼.
+	bool amend_coordinates_from_1st_floor_to_2nd_floor(int & coordinates_id);
+	//选择最近的搬运器, return true:选左边, return false:选右边
+	bool choice_nearest_carrier(int dispatch_source, int coordinates_id_1, int coordinates_id_2);
+	//判断取车的路径
+	Parkspace_path get_pickup_path(int dispatch_source, int dispatch_destination);
+	//检查停车位和取车位, 判断是否能改道
+	bool is_able_redirect(int pickup_parkspace_id, int store_parkspace_id);
+
+	//搬运器尝试空间加锁
+	Error_manager carrier_try_space_lock(int row_min, int column_min, int row_max, int column_max, int carrier_id, int & avoid_catcher_id );
+	//抓取器尝试空间加锁
+	Error_manager catcher_try_space_lock(int row_min, int column_min, int row_max, int column_max, int catcher_id );
+	//搬运器强制空间加锁(不做判断了, 直接加锁)
+	Error_manager carrier_force_space_lock(int row_min, int column_min, int row_max, int column_max, int carrier_id );
+	//抓取器强制空间加锁(不做判断了, 直接加锁)
+	Error_manager catcher_force_space_lock(int row_min, int column_min, int row_max, int column_max, int catcher_id );
+	//搬运器解锁, 退回电梯井, 全部解锁
+	Error_manager carrier_space_unlock(int carrier_id);
+	//抓取器解锁, 上升到最上层, 全部解锁, 保留4楼的空间锁
+	Error_manager catcher_space_unlock(int catcher_coordinates_id, int catcher_id);
+	//抓取器 加锁3楼和4楼的2*3个车位
+	Error_manager catcher_3rd_4st_floor_space_lock(int catcher_4st_floor_coordinates_columns, int catcher_id);
+public://get or set member variable
+
+	void set_space_lock(int space_rows, int space_columns, int catcher_id, int carrier_id);
+	void set_space_lock_for_catcher(int space_rows, int space_columns, int catcher_id);
+	void set_space_lock_for_carrier(int space_rows, int space_columns, int carrier_id);
+
+	void set_space_lock(int space_id, int catcher_id, int carrier_id);
+	void set_space_lock_for_catcher(int space_id, int catcher_id);
+	void set_space_lock_for_carrier(int space_id, int carrier_id);
+
+	void cout_space_lock();
+
+protected://member functions
+
+public://member variable
+
+	std::mutex											m_lock;
+	//空间锁, 防撞. (存放着调度设备的id集合, 交接过程中, 允许两个个设备占有同一个空间)
+	space_device**										mpp_space_lock;						//空间锁, 二维数组, 存放着调度设备的id集合, 内存由本模块管理, (默认11*15=165)
+	int													m_space_lock_rows;					//空间锁, 行		(默认11)
+	int													m_space_lock_columns;				//空间锁, 列		(默认15)
+	int													m_space_lock_total;					//空间锁, 总数	(默认165)
+	int 												m_liftway_width;					//电梯井道宽, 默认占有3列车位
+
+
+
+	//楼上车位的坐标 1~165
+	std::map<int, Point3D_tool::Point3D>	m_packspace_coordinates_map;
+
+	//一楼出入口的坐标 1100~1107
+	std::map<int, Point3D_tool::Point3D>	m_passageway_coordinates_map;
+
+	//搬运器在2~4楼交界处 的坐标 1201~1206 1301~1306 1401~1406
+	//搬运器在电梯井的坐标 2101~2112 2201~2212
+	//搬运器在一楼出入口的坐标 1100 和 1107
+	std::map<int, Point3D_tool::Point3D>	m_carrier_coordinates_map;
+
+	//机器手在2~4楼交界处 的坐标 1201~1206 1301~1306 1401~1406
+	//机器手在一楼出入口的坐标 1101~1106
+	std::map<int, Point3D_tool::Point3D>	m_catcher_coordinates_map;
+
+
+	Point3D_tool::Point3D_box				m_carrier_box;//搬运器 限定范围DISPATCH_CARRIER_PICKUP_END
+	Point3D_tool::Point3D_box				m_catcher_box;//机器手 限定范围
+
+	float									m_catcher_b_min;
+	float									m_catcher_b_max;
+	float									m_catcher_d1_min;
+	float									m_catcher_d1_max;
+	float									m_catcher_d2_min;
+	float									m_catcher_d2_max;
+
+
+	float 									m_default_wheelbase;		//默认轴距 2700mm
+
+	float 									m_catcher_1th_floor_z;			//机器手在1楼的z周高度, 1
+	float 									m_catcher_2th_floor_z;			//机器手在2楼的z周高度, 2620
+	float 									m_catcher_3th_floor_z;			//机器手在3楼的z周高度, 5220
+	float 									m_catcher_4th_floor_z;			//机器手在4楼的z周高度, 5410
+
+	float 									m_carrier_1th_floor_z;			//搬运器在1楼的z周高度, 1
+	float 									m_carrier_2th_floor_z;			//搬运器在2楼的z周高度, 2525
+	float 									m_carrier_3th_floor_z;			//搬运器在3楼的z周高度, 5125
+	float 									m_carrier_4th_floor_z;			//搬运器在4楼的z周高度, 7725
+
+	float									m_catcher_d1_d2_distance;		//机器手2D1-2D2零位间距1903mm
+	float									m_catcher_wheel_base_limit;		//机器手下降过程中的轮距限制 3000mm
+
+	float									m_carrier_y_y1_distance;		//小跑车 y-y1的间距1500mm
+	float									m_carrier_default_y1_back;		//小跑车的默认y1, 回到中跑车 4500mm
+	float									m_carrier_default_y1_leave;		//小跑车的默认y1, 离开中跑车 10500mm
+	float									m_carrier_default_y_back;		//小跑车的默认y, 回到中跑车 3000mm
+	float									m_carrier_default_y_leave;		//小跑车的默认y, 离开中跑车 9000mm
+
+	float									m_carrier_default_x_left;		//中跑车的默认x, 左侧电梯井 1mm
+	float									m_carrier_default_x_right;		//中跑车的默认x, 左侧电梯井 32600mm
+
+	int										m_passageway_terminal_id_min;		//通道口终端id最小值, 默认0
+	int										m_passageway_terminal_id_max;		//通道口终端id最大值, 默认7
+	int										m_passageway_terminal_number;		//通道口终端个数, 默认8
+	std::map<int, Passageway_functioning_pattern>	m_passageway_functioning_pattern_map;//出入口的功能模式
+
+	int										m_parkspace_id_min;					//车位id最小值, 默认1
+	int										m_parkspace_id_max;					//车位id最小值, 默认165
+	int										m_parkspace_id_total;				//车位id总数, 默认165
+
+	int										m_third_floor_parkspace_id_min;		//3楼车位id最小值, 默认19
+	int										m_third_floor_parkspace_id_max;		//3楼车位id最小值, 默认27
+	int										m_third_floor_parkspace_id_total;	//3楼车位id总数, 默认9
+
+	int										m_car_wheel_base_min;			//汽车轮距最小值, 默认1000
+	int										m_car_wheel_base_max;			//汽车轮距最大值, 默认4000
+
+	float 									m_separated_distance_z;		//机器人和搬运器分离时的z轴距离, 默认190
+	float 									m_separated_distance_x;		//机器人和搬运器分离时的x轴距离, 默认3600
+private:
+
+};
+
+
+#endif //NNXX_TESTS_DISPATCH_COORDINATES_H

+ 218 - 0
plc调度节点/dispatch/dispatch_ground_lidar.cpp

@@ -0,0 +1,218 @@
+//
+// Created by huli on 2021/9/25.
+//
+
+#include "dispatch_ground_lidar.h"
+
+Dispatch_ground_lidar::Dispatch_ground_lidar()
+{
+	m_dispatch_ground_lidar_status = DISPATCH_GROUND_LIDAR_UNKNOW;
+	m_plc_id = 0;
+	m_ground_lidar_id = 0;
+	m_ground_status_msg_updata_flag = false;
+
+}
+
+Dispatch_ground_lidar::~Dispatch_ground_lidar()
+{
+	dispatch_ground_lidar_uninit();
+}
+
+
+//调度地面雷达 初始化
+Error_manager Dispatch_ground_lidar::dispatch_ground_lidar_init(int plc_id, int ground_lidar_id)
+{
+	m_plc_id =	plc_id;
+	m_ground_lidar_id = ground_lidar_id;
+	mp_execute_thread = nullptr ;
+	m_ground_status_msg_updata_time = std::chrono::system_clock::now();
+	m_ground_status_msg_updata_flag = false;
+
+	//	线程默认开启
+	m_execute_condition.reset(false, true, false);
+	mp_execute_thread = new std::thread(&Dispatch_ground_lidar::execute_thread_fun, this);
+
+	m_dispatch_ground_lidar_status = DISPATCH_GROUND_LIDAR_READY;
+
+	return Error_code::SUCCESS;
+}
+//调度地面雷达 反初始化
+Error_manager Dispatch_ground_lidar::dispatch_ground_lidar_uninit()
+{
+	if (mp_execute_thread)
+	{
+		m_execute_condition.kill_all();
+	}
+	if (mp_execute_thread)
+	{
+		mp_execute_thread->join();
+		delete mp_execute_thread;
+		mp_execute_thread = NULL;
+	}
+
+	m_dispatch_ground_lidar_status = Dispatch_ground_lidar::DISPATCH_GROUND_LIDAR_UNKNOW;
+
+	return Error_code::SUCCESS;
+}
+//调度地面雷达 执行状态消息
+//Error_manager Dispatch_ground_lidar::execute_for_ground_status_msg(message::Ground_status_msg &ground_status_msg)
+//{
+////	std::unique_lock<std::mutex> t_lock2(m_lock);
+////	m_ground_status_msg = ground_status_msg;
+////	m_ground_status_msg_updata_time = std::chrono::system_clock::now();
+////	m_ground_status_msg_updata_flag = true;
+//	return Error_code::SUCCESS;
+//}
+
+//调度地面雷达 执行状态消息
+Error_manager Dispatch_ground_lidar::execute_for_ground_status_msg_new(measure_info &t_measure_info)
+{
+	std::unique_lock<std::mutex> t_lock2(m_lock);
+	m_measure_info = t_measure_info;
+	m_ground_status_msg_updata_time = std::chrono::system_clock::now();
+	m_ground_status_msg_updata_flag = true;
+	return Error_code::SUCCESS;
+}
+
+Dispatch_ground_lidar::Dispatch_ground_lidar_status Dispatch_ground_lidar::get_dispatch_ground_lidar_status()
+{
+	return m_dispatch_ground_lidar_status;
+}
+
+
+
+
+
+//执行外界任务的执行函数
+void Dispatch_ground_lidar::execute_thread_fun()
+{
+	LOG(INFO) << " Dispatch_ground_lidar::execute_thread_fun() start " << this;
+	Error_manager t_error;
+
+	while (m_execute_condition.is_alive())
+	{
+		m_execute_condition.wait();
+		if (m_execute_condition.is_alive())
+		{
+			std::this_thread::sleep_for(std::chrono::milliseconds(1));
+//			std::this_thread::sleep_for(std::chrono::seconds(1));
+
+			std::this_thread::yield();
+
+			if (m_ground_status_msg_updata_flag)
+			{
+
+				std::unique_lock<std::mutex> t_lock(Dispatch_communication::get_instance_references().m_data_lock);
+				std::unique_lock<std::mutex> t_lock2(m_lock);
+
+				//将nnxx的protobuf 转化为 snap7的DB块,  把店面雷达数据转发给plc
+//				int t_inlet_id = m_ground_status_msg.mutable_id_struct()->terminal_id() % 2;
+				int t_inlet_id = m_ground_lidar_id;
+				Dispatch_communication::Ground_lidar_response_from_manager_to_plc_for_data *p_response_data = &Dispatch_communication::get_instance_references().m_ground_lidar_response_from_manager_to_plc_for_data[t_inlet_id];
+				Dispatch_communication::Ground_lidar_response_from_manager_to_plc_for_key *p_response_key = &Dispatch_communication::get_instance_references().m_ground_lidar_response_from_manager_to_plc_for_key[t_inlet_id];
+				Dispatch_communication::Ground_lidar_request_from_plc_to_manager *p_request = &Dispatch_communication::get_instance_references().m_ground_lidar_request_from_plc_to_manager[t_inlet_id];
+
+
+				if (p_request->m_request_communication_mode != 2)
+				{
+					p_response_data->m_response_heartbeat = 1+p_response_data->m_response_heartbeat;
+					p_response_data->m_response_communication_mode = p_request->m_request_communication_mode;
+					p_response_data->m_response_refresh_command = p_request->m_request_refresh_command;
+
+//					p_response_data->m_response_car_center_x = m_ground_status_msg.locate_information_realtime().locate_x();
+//					p_response_data->m_response_car_center_y = m_ground_status_msg.locate_information_realtime().locate_y();
+//					p_response_data->m_response_car_angle = m_ground_status_msg.locate_information_realtime().locate_angle();
+//					p_response_data->m_response_car_front_theta = m_ground_status_msg.locate_information_realtime().locate_front_theta();
+//					p_response_data->m_response_car_length = m_ground_status_msg.locate_information_realtime().locate_length();
+//					p_response_data->m_response_car_width = m_ground_status_msg.locate_information_realtime().locate_width();
+//					p_response_data->m_response_car_height = m_ground_status_msg.locate_information_realtime().locate_height();
+//					p_response_data->m_response_car_wheel_base = m_ground_status_msg.locate_information_realtime().locate_wheel_base();
+//					p_response_data->m_response_car_wheel_width = m_ground_status_msg.locate_information_realtime().locate_wheel_width();
+//					p_response_data->m_response_uniformed_car_x = m_ground_status_msg.locate_information_realtime().uniformed_car_x();
+//					p_response_data->m_response_uniformed_car_y = m_ground_status_msg.locate_information_realtime().uniformed_car_y();
+//					p_response_data->m_response_locate_correct = m_ground_status_msg.locate_information_realtime().locate_correct();
+
+					p_response_data->m_response_car_center_x = m_measure_info.cx();
+					p_response_data->m_response_car_center_y = m_measure_info.cy();
+					p_response_data->m_response_car_angle = m_measure_info.theta();
+					p_response_data->m_response_car_front_theta = m_measure_info.front_theta();
+					p_response_data->m_response_car_length = m_measure_info.length();
+					p_response_data->m_response_car_width = m_measure_info.width();
+					p_response_data->m_response_car_height = m_measure_info.height();
+					p_response_data->m_response_car_wheel_base = m_measure_info.wheelbase();
+					p_response_data->m_response_car_wheel_width = m_measure_info.width();
+					p_response_data->m_response_uniformed_car_x = m_measure_info.cx();
+					p_response_data->m_response_uniformed_car_y = m_measure_info.cy();
+					if ( m_measure_info.ground_status() == 0 ) //ground_status  :ok 1,nothing 2,noise  3,border
+					{
+						p_response_data->m_response_locate_correct = 1;	//locate_correct  0=无效, 1=有效,
+					}
+				}
+				else if (p_response_data->m_response_refresh_command == p_request->m_request_refresh_command)
+				{
+					p_response_data->m_response_heartbeat = 1+p_response_data->m_response_heartbeat;
+					p_response_data->m_response_communication_mode = p_request->m_request_communication_mode;
+					p_response_data->m_response_refresh_command = p_request->m_request_refresh_command;
+				}
+				else
+				{
+					p_response_data->m_response_heartbeat = 1+p_response_data->m_response_heartbeat;
+					p_response_data->m_response_communication_mode = p_request->m_request_communication_mode;
+					p_response_data->m_response_refresh_command = p_request->m_request_refresh_command;
+
+//					p_response_data->m_response_car_center_x = m_ground_status_msg.locate_information_realtime().locate_x();
+//					p_response_data->m_response_car_center_y = m_ground_status_msg.locate_information_realtime().locate_y();
+//					p_response_data->m_response_car_angle = m_ground_status_msg.locate_information_realtime().locate_angle();
+//					p_response_data->m_response_car_front_theta = m_ground_status_msg.locate_information_realtime().locate_front_theta();
+//					p_response_data->m_response_car_length = m_ground_status_msg.locate_information_realtime().locate_length();
+//					p_response_data->m_response_car_width = m_ground_status_msg.locate_information_realtime().locate_width();
+//					p_response_data->m_response_car_height = m_ground_status_msg.locate_information_realtime().locate_height();
+//					p_response_data->m_response_car_wheel_base = m_ground_status_msg.locate_information_realtime().locate_wheel_base();
+//					p_response_data->m_response_car_wheel_width = m_ground_status_msg.locate_information_realtime().locate_wheel_width();
+//					p_response_data->m_response_uniformed_car_x = m_ground_status_msg.locate_information_realtime().uniformed_car_x();
+//					p_response_data->m_response_uniformed_car_y = m_ground_status_msg.locate_information_realtime().uniformed_car_y();
+//					p_response_data->m_response_locate_correct = m_ground_status_msg.locate_information_realtime().locate_correct();
+
+					p_response_data->m_response_car_center_x = m_measure_info.cx();
+					p_response_data->m_response_car_center_y = m_measure_info.cy();
+					p_response_data->m_response_car_angle = m_measure_info.theta();
+					p_response_data->m_response_car_front_theta = m_measure_info.front_theta();
+					p_response_data->m_response_car_length = m_measure_info.length();
+					p_response_data->m_response_car_width = m_measure_info.width();
+					p_response_data->m_response_car_height = m_measure_info.height();
+					p_response_data->m_response_car_wheel_base = m_measure_info.wheelbase();
+					p_response_data->m_response_car_wheel_width = m_measure_info.width();
+					p_response_data->m_response_uniformed_car_x = m_measure_info.cx();
+					p_response_data->m_response_uniformed_car_y = m_measure_info.cy();
+					if ( m_measure_info.ground_status() == 0 ) //ground_status  :ok 1,nothing 2,noise  3,border
+					{
+						p_response_data->m_response_locate_correct = 1;	//locate_correct  0=无效, 1=有效,
+					}
+				}
+
+				m_ground_status_msg_updata_flag = false;
+			}
+
+
+			//判断超时
+			{
+				std::unique_lock<std::mutex> t_lock3(m_lock);
+				if (std::chrono::system_clock::now() - m_ground_status_msg_updata_time > std::chrono::seconds(5))
+				{
+					m_dispatch_ground_lidar_status = DISPATCH_GROUND_LIDAR_DISCONNECT;
+				}
+				else
+				{
+					m_dispatch_ground_lidar_status = DISPATCH_GROUND_LIDAR_READY;
+				}
+			}
+		}
+
+	}
+}
+
+
+
+
+
+

+ 77 - 0
plc调度节点/dispatch/dispatch_ground_lidar.h

@@ -0,0 +1,77 @@
+//
+// Created by huli on 2021/9/25.
+//
+
+#ifndef NNXX_TESTS_DISPATCH_GROUND_LIDAR_H
+#define NNXX_TESTS_DISPATCH_GROUND_LIDAR_H
+
+#include "../error_code/error_code.h"
+#include <glog/logging.h>
+#include <thread>
+#include <mutex>
+#include "../tool/thread_condition.h"
+#include "../tool/common_data.h"
+#include "../tool/time_tool.h"
+#include "../task/task_base.h"
+//#include "../message/dispatch_message.pb.h"
+//#include "../message/measure_message.pb.h"
+#include "../message/message.pb.h"
+#include "../dispatch/dispatch_communication.h"
+
+//调度地面雷达
+class Dispatch_ground_lidar
+{
+public:
+	//调度plc状态
+	enum Dispatch_ground_lidar_status
+	{
+		DISPATCH_GROUND_LIDAR_UNKNOW               	= 0,    //未知
+		DISPATCH_GROUND_LIDAR_READY               	= 1,    //准备,待机
+
+
+		DISPATCH_GROUND_LIDAR_FAULT					= 10,	//故障
+		DISPATCH_GROUND_LIDAR_DISCONNECT			= 11, 	//断连
+
+	};
+public:
+	Dispatch_ground_lidar();
+	Dispatch_ground_lidar(const Dispatch_ground_lidar& other)= default;
+	Dispatch_ground_lidar& operator =(const Dispatch_ground_lidar& other)= default;
+	~Dispatch_ground_lidar();
+public://API functions
+	//调度地面雷达 初始化
+	Error_manager dispatch_ground_lidar_init(int plc_id, int ground_lidar_id);
+	//调度地面雷达 反初始化
+	Error_manager dispatch_ground_lidar_uninit();
+	//调度地面雷达 执行状态消息
+//	Error_manager execute_for_ground_status_msg(message::Ground_status_msg &ground_status_msg);
+	//调度地面雷达 执行状态消息
+	Error_manager execute_for_ground_status_msg_new(measure_info &t_measure_info);
+public://get or set member variable
+	Dispatch_ground_lidar_status get_dispatch_ground_lidar_status();
+protected://member functions
+	//执行外界任务的执行函数
+	void execute_thread_fun();
+protected://member variable
+	std::atomic<Dispatch_ground_lidar_status>				m_dispatch_ground_lidar_status;//调度地面雷达的状态
+
+
+	int 										m_plc_id;				//设备id, 索引, 就是楚天车库的单元号.
+	int 										m_ground_lidar_id;		//地面雷达的id
+	std::mutex									m_lock;	//锁
+
+	//任务执行线程
+	std::thread*        						mp_execute_thread;   			//执行的线程指针,内存由本类管理
+	Thread_condition							m_execute_condition;			//执行的条件变量
+
+	//数据缓存
+//	message::Ground_status_msg 						m_ground_status_msg;				//旧版雷达数据
+	measure_info									m_measure_info;						//新版雷达数据
+	std::chrono::system_clock::time_point			m_ground_status_msg_updata_time;	//状态更新时间点
+	std::atomic<bool>								m_ground_status_msg_updata_flag;
+private:
+
+};
+
+
+#endif //NNXX_TESTS_DISPATCH_GROUND_LIDAR_H

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 1170 - 0
plc调度节点/dispatch/dispatch_manager.cpp


+ 252 - 0
plc调度节点/dispatch/dispatch_manager.h

@@ -0,0 +1,252 @@
+//
+// Created by huli on 2020/7/20.
+//
+
+#ifndef NNXX_TESTS_DISPATCH_MANAGER_H
+#define NNXX_TESTS_DISPATCH_MANAGER_H
+
+
+#include "../error_code/error_code.h"
+#include "../communication/communication_message.h"
+#include "../system/system_communication.h"
+
+
+#include "../tool/singleton.h"
+#include "../tool/thread_condition.h"
+#include "../tool/TaskQueue/TQFactory.h"
+#include "../tool/TaskQueue/BaseTask.h"
+
+//#include "../dispatch/carrier.h"
+//#include "../dispatch/catcher.h"
+//#include "../dispatch/passageway.h"
+//#include "../dispatch/dispatch_process.h"
+
+//#include "../message/dispatch_control.pb.h"
+//#include "../message/dispatch_message.pb.h"
+#include "../dispatch/dispatch_parameter.pb.h"
+#include "../dispatch/dispatch_plc.h"
+#include "../dispatch/dispatch_ground_lidar.h"
+#include "../dispatch/dispatch_singlechip.h"
+#include "../dispatch/dispatch_command.h"
+
+//#include "../message/measure_message.pb.h"
+#include "../message/message.pb.h"
+
+
+#include <vector>
+#include <glog/logging.h>
+#include <atomic>
+
+
+//lacate测量结果结构体, 整车的信息,
+typedef struct Locate_information
+{
+	float locate_x;				//整车的中心点x值, 四轮的中心
+	float locate_y;				//整车的中心点y值, 四轮的中心
+	float locate_angle;			//整车的旋转角, 四轮的旋转角
+	float locate_length;		//整车的长度, 用于规避碰撞
+	float locate_width;			//整车的宽度, 用于规避碰撞
+	float locate_height;		//整车的高度, 用于规避碰撞
+	float locate_wheel_base;	//整车的轮距, 前后轮的距离, 用于机器人或agv的抓车
+	float locate_wheel_width;	//整车的轮距, 左右轮的距离, 用于机器人或agv的抓车
+	bool locate_correct;		//整车的校准标记位
+	//注:理论上, 车宽和左右轮距应该是一样的, 但是实际上车宽比左右轮距略大,
+}Locate_information;
+
+//调度管理模块
+class Dispatch_manager:public Singleton<Dispatch_manager>
+{
+// 子类必须把父类设定为友元函数,这样父类才能使用子类的私有构造函数。
+	friend class Singleton<Dispatch_manager>;
+
+public:
+//调度设备参数
+#define DISPATCH_DEVICE_PARAMETER_PATH "../setting/dispatch_device.prototxt"
+//存车任务数量的限制, 大于等于限则, 则使用缓存位, 默认5个
+#define DISPATCH_MANAHER_STORE_LIST_SIZE_LIMIT		5
+
+
+	//调度管理 的状态
+	enum Dispatch_manager_status
+	{
+		E_DISPATCH_MANAGER_UNKNOW               = 0,    //未知
+		E_DISPATCH_MANAGER_READY                = 1,    //准备,待机
+
+		E_DISPATCH_MANAGER_BUSY					= 2, 	//工作正忙
+		E_DISPATCH_MANAGER_DISCONNECT			= 3, 	//断连
+
+		E_DISPATCH_MANAGER_REQUEST				= 4, 	//给plc发送请求
+		E_DISPATCH_MANAGER_WORKING				= 5, 	//plc工作中
+		E_DISPATCH_MANAGER_REALLOCATE			= 6, 	//重新分配车位
+		E_DISPATCH_MANAGER_RESPONSE				= 7, 	//给主控答复
+
+		E_DISPATCH_MANAGER_STORE                = 8,    //正在存车
+		E_DISPATCH_MANAGER_PICKUP               = 9,    //正在取车
+
+
+		//新版
+		E_DISPATCH_MANAGER_COUNT_NEW			= 11,    //第一步, 接受排序模块的计数, (当数据库有指令时,排序模块会给调度发一个排队总数)
+		E_DISPATCH_MANAGER_REQUEST_NEW 			= 12,    //第二步, 发送调度任务申请,(当调度模块空闲时,向排序模块发送调度任务申请)
+		E_DISPATCH_MANAGER_POST_NEW   			= 13,    //第三不, 接受调度指令(具体的存车取车任务)
+		E_DISPATCH_MANAGER_COMPLETED_NEW 		= 14,    //第四步, 答复调度指令(具体的存车取车任务)
+
+		E_DISPATCH_MANAGER_FAULT               = 100,  //故障
+	};
+
+	//调度方向, 停车取车
+//	enum Dispatch_motion_direction
+//	{
+//		E_STORE_CAR             =0,         //停车, 出入口 -> 停车位
+//		E_PICKUP_CAR            =1,         //取车, 停车位 -> 出入口
+//	};
+
+
+private:
+	// 父类的构造函数必须保护,子类的构造函数必须私有。
+	Dispatch_manager();
+public:
+	//必须关闭拷贝构造和赋值构造,只能通过 get_instance 函数来进行操作唯一的实例。
+	Dispatch_manager(const Dispatch_manager& other) = delete;
+	Dispatch_manager& operator =(const Dispatch_manager& other) = delete;
+	~Dispatch_manager();
+public://API functions
+	//调度管理 初始化
+	Error_manager dispatch_manager_init(int dispatch_manager_id);
+	Error_manager dispatch_manager_init();
+	//初始化 调度管理 模块。从文件读取
+	Error_manager dispatch_manager_init_from_protobuf(std::string prototxt_path);
+	//初始化 调度管理 模块。从protobuf读取
+	Error_manager dispatch_manager_init_from_protobuf(Dispatch_proto::Dispatch_device_parameter_all& dispatch_device_parameter_all);
+	//调度管理 反初始化
+	Error_manager dispatch_manager_uninit();
+
+	//调度管理 设备复位
+	Error_manager dispatch_manager_device_reset();
+
+	//新的对外接口, 负责接受Rabbitmq_message,然后内部处理
+	Error_manager execute_rabbitmq_message_new(Rabbitmq_message* p_msg);
+	//给dispatch_plc底层提供接口, ack答复服务器,
+	Error_manager ack_rabbitmq_message_new();
+
+	//对外的接口函数,负责接受并处理任务单,
+//	Error_manager execute_task(Dispatch_manager::Dispatch_motion_direction dispatch_motion_direction);
+
+	//检查能否执行消息指令
+	Error_manager check_execute_msg(Rabbitmq_message* p_msg);
+	//检查状态
+	Error_manager check_status();
+
+	//调度模块 //执行搬运请求(主控->调度管理)
+//	Error_manager execute_for_dispatch_request_msg(message::Dispatch_request_msg &dispatch_request_msg);
+//	//调度模块 答复数据异常
+//	Error_manager send_dispatch_response_msg_with_error(message::Dispatch_request_msg &dispatch_request_msg, Error_manager error);
+//
+//	//调度模块 //调度总规划的答复(调度算法->调度管理)
+//	Error_manager execute_for_dispatch_plan_response_msg(message::Dispatch_plan_response_msg &dispatch_plan_response_msg);
+//	//调度模块 //调度控制的任务请求(调度算法->调度管理)
+//	Error_manager execute_for_dispatch_control_request_msg(message::Dispatch_control_request_msg &dispatch_control_request_msg);
+	//定时发送 调度管理的状态
+	Error_manager encapsulate_send_dispatch_manager_status();
+	//定时发送 调度管理的状态
+	Error_manager encapsulate_send_dispatch_manager_status_new();
+
+	//在流程的map 里面释放指定的流程
+	Error_manager release_dispatch_process(std::string command_key);
+
+	//调度模块 ///地面雷达的状态消息(地面雷达->null)
+//	Error_manager execute_for_ground_status_msg(message::Ground_status_msg ground_status_msg);
+	//调度模块 ///单片机的状态消息
+//	Error_manager execute_for_singlechip_data_msg(message::Singlechip_data singlechip_data_msg, bool validity);
+
+	//获取空闲的出口,返回0表示没有空闲出口, 返回1~6表示对应的出口
+	int get_outlet_for_ready();
+
+public://get or set member variable
+	Dispatch_manager_status get_dispatch_manager_status();
+	int get_dispatch_manager_id();
+	void set_dispatch_manager_id(int dispatch_id);
+
+protected:
+	//资源分配
+//	void resource_allocation();
+
+	//新版流程控制
+//	void process_control();
+
+	//新版流程控制
+	void process_sql();
+
+
+public://member variable
+
+	Dispatch_manager_status						m_dispatch_manager_status;			//调度管理 的状态
+	int 										m_dispatch_manager_id;						//调度模块的id, (楚天项目就是单元号, 0~2)
+
+	//流程控制
+	std::mutex                              	m_lock;        						//线程池的锁, 增删流程时要加锁.
+
+
+	//调度plc
+	Dispatch_plc								m_dispatch_plc;						//调度plc
+	Dispatch_ground_lidar						m_dispatch_ground_lidar[2];			//调度地面雷达
+	Dispatch_singlechip							m_dispatch_singlechip[4];			//调度单片机
+	int 										m_plc_floor;						//穿梭机所在的楼层, 存车完在对应的车位楼层, 取车完在1楼
+
+
+	//请求指令的list, 按照创建顺序排序, 先来后到, 停车和停车不能插队, 但是停车和取车可以插队.
+//	std::list<message::Dispatch_request_msg>				m_dispatch_request_store_list;					//存车请求指令的list, 内存由线程池管理
+//	std::list<message::Dispatch_request_msg>				m_dispatch_request_pickup_list;					//取车请求指令的list, 内存由线程池管理
+//	Common_data::Dispatch_motion_direction					m_dispatch_motion_direction_next;				//下一次的调度方向, 保证存车取车交替进行
+
+
+//	std::map<std::chrono::system_clock::time_point , message::Dispatch_response_msg>
+//															m_dispatch_response_store_map;					//存车dafu de map, 内存由线程池管理, time_point
+//	std::map<int , message::Dispatch_response_msg>			m_dispatch_response_pickup_map;					//取车dafu de map, 内存由线程池管理, int:outlet_id
+//	std::chrono::system_clock::time_point					m_store_updata_time;									//
+//	std::chrono::system_clock::time_point					m_pickup_updata_time;									//
+
+	//调度总管理的线程, 负责资源分配
+	std::thread*                        		m_dispatch_manager_thread;        	//调度总管理的线程, 总控全局, 控制每个流程的先后顺序, 并合理的分配资源.
+	Thread_condition				    		m_dispatch_manager_condition;		//调度总管理的条件变量, 总控全局, 控制每个流程的先后顺序, 并合理的分配资源.
+
+	//新版调度,消息缓存
+	int 										m_device_floor;	//设别楼层, 初始化为0
+	bool 										m_count_flag;						//接受排序模块的计数 的标志位,
+	Rabbitmq_message							m_count_command_signal_msg;			//第一步, 接受排序模块的计数, (当数据库有指令时,排序模块会给调度发一个排队总数)
+	Rabbitmq_message							m_request_command_msg;				//第二步, 发送调度任务申请,(当调度模块空闲时,向排序模块发送调度任务申请)
+	bool 										m_post_flag;						//接受调度指令 的标志位,
+	Rabbitmq_message							m_post_command_msg;					//第三不, 接受调度指令(具体的存车取车任务)
+	Rabbitmq_message							m_command_completed_msg;			//第四步, 答复调度指令(具体的存车取车任务)
+
+	Common_data::Dispatch_process_type			m_dispatch_process_type ;			//调度流程类型
+	park_table									m_park_table_msg;					//停车表单
+	pick_table									m_pick_table_msg;					//取车表单
+	Common_data::Car_type						m_car_type;							//车的大小
+
+	Dispatch_command							m_dispatch_command;					//调度指令模块
+
+
+	//地面雷达
+	Rabbitmq_message							m_measure_statu_msg_1;
+	Rabbitmq_message							m_measure_statu_msg_2;
+	measure_info								m_measure_info_1;
+	measure_info								m_measure_info_2;
+
+	//出入口单片机
+	Rabbitmq_message							m_in_mcpu_statu_msg_1;
+	Rabbitmq_message							m_in_mcpu_statu_msg_2;
+	in_mcpu_statu								m_in_mcpu_statu_1;
+	in_mcpu_statu								m_in_mcpu_statu_2;
+	Rabbitmq_message							m_out_mcpu_statu_msg_1;
+	Rabbitmq_message							m_out_mcpu_statu_msg_2;
+	out_mcpu_statu								m_out_mcpu_statu_1;
+	out_mcpu_statu								m_out_mcpu_statu_2;
+
+
+	std::chrono::system_clock::time_point		m_request_updata_time;	//请求更新时间
+private:
+
+};
+
+
+#endif //NNXX_TESTS_DISPATCH_MANAGER_H

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 7243 - 0
plc调度节点/dispatch/dispatch_parameter.pb.cc


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 4834 - 0
plc调度节点/dispatch/dispatch_parameter.pb.h


+ 214 - 0
plc调度节点/dispatch/dispatch_parameter.proto

@@ -0,0 +1,214 @@
+
+syntax = "proto2";
+package Dispatch_proto;
+
+message Catcher_parameter
+{
+    required int32                  id = 1;
+    required int32                  key = 2;
+}
+
+message Carrier_parameter
+{
+    required int32                  id = 1;
+    required int32                  key = 2;
+}
+
+message Passageway_parameter
+{
+    required int32                  id = 1;
+    required int32                  key = 2;
+}
+
+
+
+message Dispatch_device_parameter_all
+{
+    required int32                  catcher_size=1;
+    repeated Catcher_parameter      catcher_parameters=2;
+    required int32                  carrier_size=3;
+    repeated Carrier_parameter      carrier_parameters=4;
+    required int32                  passageway_size=5;
+    repeated Passageway_parameter   passageway_parameters=6;
+
+}
+
+
+
+
+
+
+
+
+/*
+        Packspace_coordinates   id 的表示含义
+
+        1~165           2楼~12楼的停车位
+
+        1100            0号出口(在一楼)(目前没有)
+        1101~1106       1~6号出入口 (在一楼)
+        1107            7号出口(在一楼)
+        1201~1206       1~6号出入口上方2楼处
+        1301~1306       1~6号出入口上方3楼处
+        1401~1406       1~6号出入口上方4楼处
+
+        2101~2112       左侧电梯井(1楼~12楼)(一号搬运器的待机点)
+        2201~2212       右侧电梯井(1楼~12楼)(二号搬运器的待机点)
+
+(由于工程问题, 每一个车位的x值略有不同, 不是等比数列)
+*/
+
+//楼上车位的坐标 1~165
+message Packspace_coordinates_parameter
+{
+    optional int32                  id = 1[default = 0];
+    optional int32                  x = 2[default = 0];
+    optional int32                  y = 3[default = 0];
+    optional int32                  z = 4[default = 0];
+}
+//一楼出入口的坐标 1100~1107
+message Passageway_coordinates_parameter
+{
+    optional int32                  id = 1[default = 0];
+    optional int32                  x = 2[default = 0];
+    optional int32                  y = 3[default = 0];
+    optional int32                  z = 4[default = 0];
+}
+
+//搬运器在2~4楼交界处 的坐标 1201~1206 1301~1306 1401~1406
+//搬运器在电梯井的坐标 2101~2112 2201~2212
+//机器手在一楼出入口的坐标 1100 和 1107
+message Carrier_coordinates_parameter
+{
+    optional int32                  id = 1[default = 0];
+    optional int32                  x = 2[default = 0];
+    optional int32                  y = 3[default = 0];
+    optional int32                  z = 4[default = 0];
+}
+
+//机器手在2~4楼交界处 的坐标 1201~1206 1301~1306 1401~1406
+//机器手在一楼出入口的坐标 1101~1106
+message Catcher_coordinates_parameter
+{
+    optional int32                  id = 1[default = 0];
+    optional int32                  x = 2[default = 0];
+    optional int32                  y = 3[default = 0];
+    optional int32                  z = 4[default = 0];
+}
+//注意了, 搬运器和机器手在同层的z轴坐标是不同的, 机器手比搬运器高一点.
+//x轴和y必须相同,
+//搬运器和机器手交接时 使用汽车前轮对齐, 搬运器的Y1固定不同, 所以其他的3个夹杆需要根须轴距来计算.
+
+
+//搬运器 限定范围
+message Carrier_box_parameter
+{
+    optional int32                  x_min = 1[default = -1000000];
+    optional int32                  x_max = 2[default = 1000000];
+    optional int32                  y_min = 3[default = -1000000];
+    optional int32                  y_max = 4[default = 1000000];
+    optional int32                  z_min = 5[default = -1000000];
+    optional int32                  z_max = 6[default = 1000000];
+}
+
+
+//机器手 限定范围
+message Catcher_box_parameter
+{
+    optional int32                  x_min = 1[default = -1000000];
+    optional int32                  x_max = 2[default = 1000000];
+    optional int32                  y_min = 3[default = -1000000];
+    optional int32                  y_max = 4[default = 1000000];
+    optional int32                  z_min = 5[default = -1000000];
+    optional int32                  z_max = 6[default = 1000000];
+}
+
+message Axis_range_parameter
+{
+    optional int32                  min = 1[default = -1000000];
+    optional int32                  max = 2[default = 1000000];
+}
+
+//出入口的功能模式
+enum Passageway_functioning_pattern
+{
+    PASSAGEWAY_FUNCTIONING_PATTERN_UNKNOWN          = 0;    //未知
+    PASSAGEWAY_FUNCTIONING_PATTERN_INLET            = 1;    //单向入口
+    PASSAGEWAY_FUNCTIONING_PATTERN_OUTLET           = 2;    //单向出口
+    PASSAGEWAY_FUNCTIONING_PATTERN_BIDIRECTION      = 3;    //双向口
+}
+
+message Parkspace_number
+{
+    required int32                  rows = 1;
+    required int32                  columns = 2;
+    required int32                  total = 3;
+    required int32                  liftway_width = 4;
+}
+
+message Dispatch_coordinates_parameter_all
+{
+    repeated Packspace_coordinates_parameter            packspace_coordinates_parameters = 1;
+    repeated Passageway_coordinates_parameter           passageway_coordinates_parameters = 2;
+    repeated Carrier_coordinates_parameter              carrier_coordinates_parameters = 3;
+    repeated Catcher_coordinates_parameter              catcher_coordinates_parameters = 4;
+
+
+    optional Carrier_box_parameter                      carrier_box_parameters = 5;
+
+    optional Catcher_box_parameter                      catcher_box_parameters = 6;
+    optional int32                                      catcher_b_min = 7;
+    optional int32                                      catcher_b_max = 8;
+    optional int32                                      catcher_d1_min = 9;
+    optional int32                                      catcher_d1_max = 10;
+    optional int32                                      catcher_d2_min = 11;
+    optional int32                                      catcher_d2_max = 12;
+
+
+    optional int32                                      default_wheelbase = 13;
+
+    optional int32                                      catcher_1th_floor_z = 14;
+    optional int32                                      catcher_2th_floor_z = 15;
+    optional int32                                      catcher_3th_floor_z = 16;
+    optional int32                                      catcher_4th_floor_z = 17;
+
+    optional int32                                      carrier_1th_floor_z = 18;
+    optional int32                                      carrier_2th_floor_z = 19;
+    optional int32                                      carrier_3th_floor_z = 20;
+    optional int32                                      carrier_4th_floor_z = 21;
+
+    optional int32                                      catcher_d1_d2_distance = 22;
+    optional int32                                      catcher_wheel_base_limit = 23;
+
+    optional int32                                      carrier_y_y1_distance = 24;
+    optional int32                                      carrier_default_y1_back = 25;
+    optional int32                                      carrier_default_y1_leave = 26;
+    optional int32                                      carrier_default_y_back = 27;
+    optional int32                                      carrier_default_y_leave = 28;
+
+    optional int32                                      carrier_default_x_left = 29;
+    optional int32                                      carrier_default_x_right = 30;
+
+    optional int32                                      passageway_terminal_id_min = 31;
+    optional int32                                      passageway_terminal_id_max = 32;
+    optional int32                                      passageway_terminal_number = 33;
+    repeated Passageway_functioning_pattern             passageway_functioning_patterns = 34;
+
+    optional int32                                      parkspace_id_min = 35;
+    optional int32                                      parkspace_id_max = 36;
+    optional int32                                      parkspace_id_total = 37;
+
+    optional int32                                      third_floor_parkspace_id_min = 38;
+    optional int32                                      third_floor_parkspace_id_max = 39;
+    optional int32                                      third_floor_parkspace_id_total = 40;
+
+    optional int32                                      car_wheel_base_min = 41;
+    optional int32                                      car_wheel_base_max = 42;
+
+    required Parkspace_number                           parkspace_number=43;
+
+    optional int32                                      m_separated_distance_z=44;
+    optional int32                                      m_separated_distance_x=45;
+
+
+}

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 1156 - 0
plc调度节点/dispatch/dispatch_plc.cpp


+ 254 - 0
plc调度节点/dispatch/dispatch_plc.h

@@ -0,0 +1,254 @@
+//
+// Dispatch_plc 调度plc模块, 主要是负责对接plc的通信数据缓存,以及调度主流程
+//	本地缓存DB块的的数据, 内部线程负责下发任务指令和验收任务指令.
+//
+
+#ifndef NNXX_TESTS_DISPATCH_PLC_H
+#define NNXX_TESTS_DISPATCH_PLC_H
+
+#include "../error_code/error_code.h"
+#include <glog/logging.h>
+#include <thread>
+#include <mutex>
+#include "../tool/thread_condition.h"
+#include "../tool/common_data.h"
+#include "../tool/time_tool.h"
+#include "../task/task_base.h"
+//#include "../message/dispatch_message.pb.h"
+#include "../message/message.pb.h"
+#include "../dispatch/dispatch_communication.h"
+
+#include "../tool/string_convert.h"
+
+//调度plc
+class Dispatch_plc
+{
+	//设备底层通信延时5000ms
+#define	COMMUNICATION_OVER_TIME_MS	5000
+
+	//调度指令超时时间 3600000 ms = 60 min
+#define DISPATCH_PROCESS_TIMEOUT_MS							3600000
+//调度指令超时时间  衰减值 在原有的基础上减少10秒
+#define DISPATCH_PROCESS_ATTENUATION_TIMEOUT_MS				10000
+
+public:
+//调度plc状态
+	enum Dispatch_plc_status
+	{
+		DISPATCH_PLC_UNKNOW               	= 0,    //未知
+		DISPATCH_PLC_READY               	= 1,    //准备,待机
+		DISPATCH_PLC_BUSY					= 2, 	//工作正忙, 暂时不用
+		DISPATCH_PLC_DISCONNECT				= 3, 	//断连
+
+		DISPATCH_PLC_REQUEST				= 4, 	//给plc发送请求
+		DISPATCH_PLC_WORKING				= 5, 	//plc工作中
+		DISPATCH_PLC_RESPONSE				= 6, 	//给主控答复
+
+
+		DISPATCH_PLC_FAULT					= 100,	//故障
+	};
+
+	//指令完成状态, 设备答复指令, 返回任务完成的情况
+	enum Response_status
+	{
+		RESPONS_WORKING            	= 0,    //任务进行中
+		RESPONS_OVER               	= 1,    //任务完成
+		RESPONS_ERROR				= 2,	//错误
+
+		RESPONS_REALLOCATE_MIN_CAR     	= 11,    //重新分配小车
+		RESPONS_REALLOCATE_MID_CAR     	= 12,    //重新分配中车
+		RESPONS_REALLOCATE_BIG_CAR     	= 13,    //重新分配大车
+		RESPONS_REALLOCATE_HUGE_CAR     	= 14,    //重新分配fault
+		RESPONS_REALLOCATE_FAULT_CAR     	= 15,    //重新分配fault
+
+		RESPONS_MINOR_ERROR			= 100,	//一般故障, 可恢复
+		RESPONS_CRITICAL_ERROR		= 101,	//致命故障,不可恢复
+	};
+
+public:
+	Dispatch_plc();
+	Dispatch_plc(const Dispatch_plc& other)= default;
+	Dispatch_plc& operator =(const Dispatch_plc& other)= default;
+	~Dispatch_plc();
+public://API functions
+	//调度plc 初始化
+	Error_manager dispatch_plc_init(int plc_id);
+	//调度plc 反初始化
+	Error_manager dispatch_plc_uninit();
+	//调度plc 执行请求
+//	Error_manager execute_for_dispatch_request_msg(message::Dispatch_request_msg &dispatch_request_msg);
+	//新版调度plc 执行请求 存车
+	Error_manager execute_for_dispatch_request_msg(park_table &park_table_msg, Common_data::Dispatch_process_type dispatch_process_type, Common_data::Car_type car_type);
+	//新版调度plc 执行请求 取车
+	Error_manager execute_for_dispatch_request_msg(pick_table &pick_table_msg, Common_data::Dispatch_process_type dispatch_process_type, Common_data::Car_type car_type);
+
+public://get or set member variable
+	Dispatch_plc::Dispatch_plc_status get_dispatch_plc_status();
+//	message::Dispatch_request_msg get_dispatch_request_msg();
+	Error_manager get_result();
+	float get_response_working_total_time();
+	float get_response_working_remaining_time();
+	void clear_request_msg();
+protected://member functions
+    //jiancha qingqiu xiaoxi
+//    Error_manager check_dispatch_request_msg(message::Dispatch_request_msg & dispatch_request_msg);
+
+	//执行外界任务的执行函数
+	void execute_thread_fun();
+
+	//封装 给plc的调度请求
+	Error_manager encapsulate_dispatch_request_to_plc();
+	//封装 给plc的调度请求
+	Error_manager encapsulate_dispatch_request_to_plc_new();
+	//更新plc通信
+	Error_manager update_dispatch_plc_communication();
+	//检查plc答复反馈
+	Error_manager check_response_from_plc();
+	//检查plc答复反馈
+	Error_manager check_response_from_plc_new();
+	//发送调度答复信息给主控
+	Error_manager send_dispatch_response_to_main_control();
+	//发送调度答复信息给主控
+	Error_manager send_dispatch_response_to_main_control_new();
+
+
+protected://member variable
+public:
+	std::atomic<Dispatch_plc_status>			m_dispatch_plc_status;			//设备总状态, 控制任务流程(长流程)
+	int 										m_plc_id;				//设备id, 索引, 就是楚天车库的单元号.
+	std::mutex									m_lock;	//锁
+
+	//任务执行线程
+	std::thread*        						mp_execute_thread;   			//执行的线程指针,内存由本类管理
+	Thread_condition							m_execute_condition;			//执行的条件变量
+
+
+	//指令
+	Common_data::Dispatch_process_type			m_dispatch_process_type ;			//调度流程类型
+//	message::Dispatch_request_msg				m_dispatch_request_msg;				//1执行搬运请求(主控->调度管理)
+//	message::Dispatch_response_msg				m_dispatch_response_msg;			//6搬运动作执行完成后反馈结果(调度管理->主控)
+
+	park_table									m_park_table_msg;		//停车表单
+	pick_table									m_pick_table_msg;		//取车表单
+//	int 										m_terminal_id;			//出入口id
+	Common_data::Car_type						m_car_type;							//车的大小
+
+
+
+	std::string									m_command_key;						//任务唯一码, 索引
+	int 										m_timeout_ms;						//超时时间,单位ms
+	std::chrono::system_clock::time_point		m_start_time;						//流程开始时间
+	Error_manager								m_result;							//中间的错误码
+
+	//数据缓存
+	//调度管理给plc发送调度指令
+	std::string										m_request_key;				//请求唯一码, 用作识别
+	unsigned int									m_request_status = 0;			//请求确认标志
+	// 调度指令的起点,终点,方向
+	Common_data::Dispatch_process_type			m_request_dispatch_motion_direction ;		//调度方向	0=未知,1=存车,2=取车
+	unsigned int									m_request_passageway_id = 0;					//出入口id	6个入口和6个出口
+	Common_data::Passageway_direction				m_request_passageway_direction ;				//出入口方向	0=未知,1=入口,2=出口
+	unsigned int									m_request_parkingspace_index_id = 0;			//楼上车位索引id	1~180(3*6*13)
+	unsigned int									m_request_parkingspace_unit_id = 0;				//楼上车位单元号	1~3
+	unsigned int									m_request_parkingspace_label_id = 0;			//楼上车位标签号  1~78
+	unsigned int									m_request_parkingspace_floor_id = 0;			//楼上车位楼层号	2~11
+	unsigned int									m_request_parkingspace_room_id = 0;				//楼上车位房间号	1~6
+	Common_data::Parkingspace_direction				m_request_parkingspace_direction ;			//楼上车位方向	0=未知,1=朝南,2=朝北
+	//汽车的定位信息(地面雷达)
+	float 											m_request_car_center_x = 0;				//整车的中心点x值, 四轮的中心, 单位:米 m
+	float  											m_request_car_center_y = 0;				//整车的中心点y值, 四轮的中心, 单位:米 m
+	float  											m_request_car_angle = 0;				//整车的车身旋转角, 单位:度 (-90~90)
+	float  											m_request_car_front_theta = 0;			//整车的前轮的旋转角, 单位:度 (-90~90)
+	float  											m_request_car_length = 0;				//整车的长度, 用于规避碰撞, 单位:米 m
+	float  											m_request_car_width = 0;				//整车的宽度, 用于规避碰撞, 单位:米 m
+	float  											m_request_car_height = 0;				//整车的高度, 用于规避碰撞, 单位:米 m
+	float  											m_request_car_wheel_base = 0;			//整车的轮距, 前后轮的距离, 用于机器人或agv的抓车, 单位:米 m
+	float  											m_request_car_wheel_width = 0;			//整车的轮距, 左右轮的距离, 用于机器人或agv的抓车, 单位:米 m
+	std::string										m_request_car_license;					//车牌号(汽车唯一标示)	例如: 鄂A12345
+
+	Common_data::Car_type							m_request_car_type;					//车的大小
+	float 											m_request_uniformed_car_x = 0;				//转角复位后,车辆中心点x
+	float  											m_request_uniformed_car_y = 0;				//转角复位后,车辆中心点y
+
+	//防撞雷达
+	Common_data::Anticollision_lidar_flag			m_request_anticollision_lidar_flag ;		//汽车是否停到正确的位置, 防撞雷达	预留, 楚天暂时不用,0=未知,1=位置正常,2=位置异常
+	//轮距雷达
+	float  											m_request_car_wheel_base_exact_value = 0;	//汽车前后轮距,轮距雷达的精确值	预留, 楚天暂时不用,单位:米 m
+
+
+	//plc给调度管理发送调度答复
+	std::string										m_response_key;									//答复唯一码, 用作识别
+	Response_status									m_response_status;			//指令完成状态, 机器人答复指令, 返回任务完成的情况
+	float											m_response_working_total_time;				//搬运总时间(秒)
+	float											m_response_working_remaining_time;			//剩余时间(秒)
+	// 调度指令的起点,终点,方向
+	Common_data::Dispatch_process_type			m_response_dispatch_motion_direction ;		//调度方向	0=未知,1=存车,2=取车
+	unsigned int									m_response_passageway_id = 0;					//出入口id	6个入口和6个出口
+	Common_data::Passageway_direction				m_response_passageway_direction ;			//出入口方向	0=未知,1=入口,2=出口
+	unsigned int									m_response_parkingspace_index_id = 0;			//楼上车位索引id	1~180(3*6*13)
+	unsigned int									m_response_parkingspace_unit_id = 0;			//楼上车位单元号	1~3
+	unsigned int									m_response_parkingspace_label_id = 0;			//楼上车位标签号	1~78
+	unsigned int									m_response_parkingspace_floor_id = 0;			//楼上车位楼层号	2~11
+	unsigned int									m_response_parkingspace_room_id = 0;			//楼上车位房间号	1~6
+	Common_data::Parkingspace_direction				m_response_parkingspace_direction ;			//楼上车位方向	0=未知,1=朝南,2=朝北
+	//汽车的定位信息(地面雷达)
+	float 											m_response_car_center_x = 0;			//整车的中心点x值, 四轮的中心, 单位:米 m
+	float  											m_response_car_center_y = 0;			//整车的中心点y值, 四轮的中心, 单位:米 m
+	float  											m_response_car_angle = 0;				//整车的车身旋转角, 单位:度 (-90~90)
+	float  											m_response_car_front_theta = 0;			//整车的前轮的旋转角, 单位:度 (-90~90)
+	float  											m_response_car_length = 0;				//整车的长度, 用于规避碰撞, 单位:米 m
+	float  											m_response_car_width = 0;				//整车的宽度, 用于规避碰撞, 单位:米 m
+	float  											m_response_car_height = 0;				//整车的高度, 用于规避碰撞, 单位:米 m
+	float  											m_response_car_wheel_base = 0;			//整车的轮距, 前后轮的距离, 用于机器人或agv的抓车, 单位:米 m
+	float  											m_response_car_wheel_width = 0;			//整车的轮距, 左右轮的距离, 用于机器人或agv的抓车, 单位:米 m
+	std::string										m_response_car_license;					//车牌号(汽车唯一标示)	例如: 鄂A12345
+
+	Common_data::Car_type							m_response_car_type;					//车的大小
+	float 											m_response_uniformed_car_x = 0;				//转角复位后,车辆中心点x
+	float  											m_response_uniformed_car_y = 0;				//转角复位后,车辆中心点y
+
+	//防撞雷达
+	Common_data::Anticollision_lidar_flag			m_response_anticollision_lidar_flag ;	//汽车是否停到正确的位置, 防撞雷达	预留, 楚天暂时不用,0=未知,1=位置正常,2=位置异常
+	//轮距雷达
+	float  											m_response_car_wheel_base_exact_value = 0;	//汽车前后轮距,轮距雷达的精确值	预留, 楚天暂时不用,单位:米 m
+
+
+	//dispatch状态
+	unsigned char			m_dispatch_heartbeat = 0;				//心跳位, 0-255循环
+
+	//plc状态信息
+	unsigned char			m_plc_heartbeat = 0;				//心跳位, 0-255循环
+	unsigned char			m_plc_status_info = 0;			//plc状态的集合
+	//0 bit, 手动模式
+	//1 bit, 自动模式
+	//2 bit, 自动运行中
+	//3 bit, 复位
+	//4 bit, 1号口可以进车
+	//5 bit, 2号口可以进车
+	//6 bit, 预留
+	//7 bit, 预留
+//	unsigned char			m_reserved2_37[36] = {0};		//预留 36个
+	float					m_turnplate_angle_min1 = 0;		//1号口转盘最小值
+	float					m_turnplate_angle_max1 = 0;		//1号口转盘最大值
+	float					m_turnplate_angle_min2 = 0;		//2号口转盘最小值
+	float					m_turnplate_angle_max2 = 0;		//2号口转盘最大值
+
+
+
+	//硬件状态, 目前只做显示判断
+	std::chrono::system_clock::time_point			m_status_updata_time;	//状态更新时间点
+	unsigned char									m_last_heartbeat;			//上一次的心跳
+
+
+
+	//test time
+	std::chrono::system_clock::time_point           test_start_time;
+	std::chrono::system_clock::time_point           test_end_time;
+
+
+private:
+
+};
+
+
+#endif //NNXX_TESTS_DISPATCH_PLC_H

+ 289 - 0
plc调度节点/dispatch/dispatch_singlechip.cpp

@@ -0,0 +1,289 @@
+//
+// Created by huli on 2021/11/18.
+//
+
+#include "dispatch_singlechip.h"
+
+
+
+Dispatch_singlechip::Dispatch_singlechip()
+{
+	m_dispatch_singlechip_status = DISPATCH_SINGLECHIP_UNKNOW;
+	m_plc_id = 0;
+	m_singlechip_id = 0;
+	m_singlechip_data_msg_updata_flag = false;
+	m_validity = false;
+
+}
+
+Dispatch_singlechip::~Dispatch_singlechip()
+{
+	dispatch_singlechip_uninit();
+}
+
+
+//调度单片机 初始化,  单片机id, 0或者1, 单片机方向, 1是入口, 2是出口
+Error_manager Dispatch_singlechip::dispatch_singlechip_init(int plc_id, int singlechip_id, int singlechip_direction)
+{
+	m_plc_id =	plc_id;
+	m_singlechip_id = singlechip_id;
+	m_singlechip_direction = singlechip_direction;
+	mp_execute_thread = nullptr ;
+	m_singlechip_data_msg_updata_time = std::chrono::system_clock::now();
+	m_singlechip_data_msg_updata_flag = false;
+
+	//	线程默认开启
+	m_execute_condition.reset(false, true, false);
+	mp_execute_thread = new std::thread(&Dispatch_singlechip::execute_thread_fun, this);
+
+	m_dispatch_singlechip_status = DISPATCH_SINGLECHIP_READY;
+
+	return Error_code::SUCCESS;
+}
+//调度单片机 反初始化
+Error_manager Dispatch_singlechip::dispatch_singlechip_uninit()
+{
+	if (mp_execute_thread)
+	{
+		m_execute_condition.kill_all();
+	}
+	if (mp_execute_thread)
+	{
+		mp_execute_thread->join();
+		delete mp_execute_thread;
+		mp_execute_thread = NULL;
+	}
+
+	m_dispatch_singlechip_status = Dispatch_singlechip::DISPATCH_SINGLECHIP_UNKNOW;
+
+	return Error_code::SUCCESS;
+}
+//调度单片机 执行状态消息
+//Error_manager Dispatch_singlechip::execute_for_singlechip_data_msg(message::Singlechip_data &singlechip_data_msg, bool validity)
+//{
+//
+////	std::unique_lock<std::mutex> t_lock2(m_lock);
+////	m_singlechip_data_msg = singlechip_data_msg;
+////	m_validity = validity;
+////	m_singlechip_data_msg_updata_time = std::chrono::system_clock::now();
+////	m_singlechip_data_msg_updata_flag = true;
+//
+//	return Error_code::SUCCESS;
+//}
+//调度单片机 执行状态消息
+Error_manager Dispatch_singlechip::execute_for_singlechip_data_msg_new(in_mcpu_statu &t_in_mcpu_statu, bool validity)
+{
+	std::unique_lock<std::mutex> t_lock2(m_lock);
+
+	m_in_mcpu_statu = t_in_mcpu_statu;
+	m_validity = validity;
+	m_singlechip_data_msg_updata_time = std::chrono::system_clock::now();
+	m_singlechip_data_msg_updata_flag = true;
+
+	return Error_code::SUCCESS;
+
+}
+//调度单片机 执行状态消息
+Error_manager Dispatch_singlechip::execute_for_singlechip_data_msg_new(out_mcpu_statu &t_out_mcpu_statu, bool validity)
+{
+	std::unique_lock<std::mutex> t_lock2(m_lock);
+
+	m_out_mcpu_statu = t_out_mcpu_statu;
+	m_validity = validity;
+	m_singlechip_data_msg_updata_time = std::chrono::system_clock::now();
+	m_singlechip_data_msg_updata_flag = true;
+
+	return Error_code::SUCCESS;
+}
+
+Dispatch_singlechip::Dispatch_singlechip_status Dispatch_singlechip::get_dispatch_singlechip_status()
+{
+	return m_dispatch_singlechip_status;
+}
+
+
+//判断出口是否空闲
+bool Dispatch_singlechip::is_outlet_ready()
+{
+	std::unique_lock<std::mutex> t_lock(m_lock);
+	//   outside_safety 0无效, 1无车, 2有车
+	if ( m_dispatch_singlechip_status == DISPATCH_SINGLECHIP_READY &&
+//		 m_singlechip_data_msg.insideexistenceflag() == 0)
+m_out_mcpu_statu.outside_safety() == 1)
+	{
+		return true;
+	}
+	else
+	{
+		return false;
+	}
+}
+
+
+//执行外界任务的执行函数
+void Dispatch_singlechip::execute_thread_fun()
+{
+	LOG(INFO) << " Dispatch_singlechip::execute_thread_fun() start " << this;
+	Error_manager t_error;
+
+	while (m_execute_condition.is_alive())
+	{
+		m_execute_condition.wait();
+		if (m_execute_condition.is_alive())
+		{
+			std::this_thread::sleep_for(std::chrono::milliseconds(1));
+//			std::this_thread::sleep_for(std::chrono::seconds(1));
+
+			std::this_thread::yield();
+
+//			std::cout << " huli test :::: " << "uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu m_singlechip_data_msg_updata_flag = " << m_singlechip_data_msg_updata_flag << std::endl;
+
+			if (m_singlechip_data_msg_updata_flag)
+			{
+
+//				std::cout << " huli test :::: " << "jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj m_singlechip_data_msg_updata_flag = " << m_singlechip_data_msg_updata_flag << std::endl;
+//				std::cout << " huli test :::: " << " m_singlechip_data_msg = " << m_singlechip_data_msg.DebugString() << std::endl;
+
+
+
+				std::unique_lock<std::mutex> t_lock(Dispatch_communication::get_instance_references().m_data_lock);
+				std::unique_lock<std::mutex> t_lock2(m_lock);
+
+				//将nnxx的protobuf 转化为 snap7的DB块,  把店面雷达数据转发给plc
+//				int t_temp = (m_singlechip_data_msg.terminalid() % 2) + (m_singlechip_data_msg.dispatchdirection()-1)*2;
+				int t_temp = (m_singlechip_direction-1)*2 + m_singlechip_id;
+				Dispatch_communication::Singlechip_response_from_manager_to_plc *p_response = &Dispatch_communication::get_instance_references().m_singlechip_response_from_manager_to_plc[t_temp];
+				Dispatch_communication::Singlechip_request_from_plc_to_manager *p_request = &Dispatch_communication::get_instance_references().m_singlechip_request_from_plc_to_manager[t_temp];
+
+				if (p_request->m_request_communication_mode != 2)
+				{
+					p_response->m_response_heartbeat = 1+p_response->m_response_heartbeat;
+//					int heartbeat = p_response->m_response_heartbeat;
+//					std::cout << " huli test :::: " << " mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmp_response->m_response_heartbeat = " << heartbeat << std::endl;
+					p_response->m_response_communication_mode = p_request->m_request_communication_mode;
+					p_response->m_response_refresh_command = p_request->m_request_refresh_command;
+					p_response->m_response_data_validity = m_validity;
+
+//					p_response->m_process_status = m_singlechip_data_msg.processstatus();
+//					p_response->m_process_control = m_singlechip_data_msg.processcontrol();
+//					p_response->m_over_border_status = m_singlechip_data_msg.overborderstatus();
+//					p_response->m_car_height_status_current = m_singlechip_data_msg.carheightstatuscurrent();
+//					p_response->m_car_height_status_passing = m_singlechip_data_msg.carheightstatuspassing();
+//					p_response->m_outside_door_status = m_singlechip_data_msg.outsidedoorstatus();
+//					p_response->m_outside_door_control = m_singlechip_data_msg.outsidedoorcontrol();
+//					p_response->m_dispatch_finish_flag = m_singlechip_data_msg.dispatchfinishflag();
+//					p_response->m_inside_existence_flag = m_singlechip_data_msg.insideexistenceflag();
+//					p_response->m_outside_existence_flag = m_singlechip_data_msg.outsideexistenceflag();
+//					p_response->m_reset_flag = m_singlechip_data_msg.resetflag();
+//					p_response->m_stop_flag = m_singlechip_data_msg.stopflag();
+//					p_response->m_error_code = 0;
+//
+//					p_response->m_gpio_input[0] = m_singlechip_data_msg.inputdi().di0();
+//					p_response->m_gpio_input[1] = m_singlechip_data_msg.inputdi().di1();
+//					p_response->m_gpio_input[2] = m_singlechip_data_msg.inputdi().di2();
+//					p_response->m_gpio_input[3] = m_singlechip_data_msg.inputdi().di3();
+//					p_response->m_gpio_input[4] = m_singlechip_data_msg.inputdi().di4();
+//					p_response->m_gpio_input[5] = m_singlechip_data_msg.inputdi().di5();
+//					p_response->m_gpio_input[6] = m_singlechip_data_msg.inputdi().di6();
+//					p_response->m_gpio_input[7] = m_singlechip_data_msg.inputdi().di7();
+//					p_response->m_gpio_input[8] = m_singlechip_data_msg.inputdi().di8();
+//					p_response->m_gpio_input[9] = m_singlechip_data_msg.inputdi().di9();
+//					p_response->m_gpio_input[10] = m_singlechip_data_msg.inputdi().di10();
+//					p_response->m_gpio_input[11] = m_singlechip_data_msg.inputdi().di11();
+//					p_response->m_gpio_input[12] = m_singlechip_data_msg.inputdi().di12();
+//					p_response->m_gpio_input[13] = m_singlechip_data_msg.inputdi().di13();
+//					p_response->m_gpio_input[14] = m_singlechip_data_msg.inputdi().di14();
+//					p_response->m_gpio_input[15] = m_singlechip_data_msg.inputdi().di15();
+
+					if ( m_singlechip_direction ==1 )
+					{
+						p_response->m_outside_door_status = m_in_mcpu_statu.door_statu()-1;
+						p_response->m_over_border_status = m_in_mcpu_statu.back_io()-1;
+						p_response->m_inside_existence_flag = m_in_mcpu_statu.is_occupy()-1;
+						p_response->m_car_height_status_current = m_in_mcpu_statu.heighth()-1;
+					}
+					else if(m_singlechip_direction ==2)
+					{
+						p_response->m_outside_door_status = m_out_mcpu_statu.door_statu()-1;
+						p_response->m_inside_existence_flag = m_out_mcpu_statu.outside_safety()-1;
+					}
+				}
+				else if (p_response->m_response_refresh_command == p_request->m_request_refresh_command)
+				{
+					p_response->m_response_heartbeat = 1+p_response->m_response_heartbeat;
+					p_response->m_response_communication_mode = p_request->m_request_communication_mode;
+					p_response->m_response_refresh_command = p_request->m_request_refresh_command;
+				}
+				else
+				{
+					p_response->m_response_heartbeat = 1+p_response->m_response_heartbeat;
+					p_response->m_response_communication_mode = p_request->m_request_communication_mode;
+					p_response->m_response_refresh_command = p_request->m_request_refresh_command;
+					p_response->m_response_data_validity = m_validity;
+
+//					p_response->m_process_status = m_singlechip_data_msg.processstatus();
+//					p_response->m_process_control = m_singlechip_data_msg.processcontrol();
+//					p_response->m_over_border_status = m_singlechip_data_msg.overborderstatus();
+//					p_response->m_car_height_status_current = m_singlechip_data_msg.carheightstatuscurrent();
+//					p_response->m_car_height_status_passing = m_singlechip_data_msg.carheightstatuspassing();
+//					p_response->m_outside_door_status = m_singlechip_data_msg.outsidedoorstatus();
+//					p_response->m_outside_door_control = m_singlechip_data_msg.outsidedoorcontrol();
+//					p_response->m_dispatch_finish_flag = m_singlechip_data_msg.dispatchfinishflag();
+//					p_response->m_inside_existence_flag = m_singlechip_data_msg.insideexistenceflag();
+//					p_response->m_outside_existence_flag = m_singlechip_data_msg.outsideexistenceflag();
+//					p_response->m_reset_flag = m_singlechip_data_msg.resetflag();
+//					p_response->m_stop_flag = m_singlechip_data_msg.stopflag();
+//					p_response->m_error_code = 0;
+//
+//					p_response->m_gpio_input[0] = m_singlechip_data_msg.inputdi().di0();
+//					p_response->m_gpio_input[1] = m_singlechip_data_msg.inputdi().di1();
+//					p_response->m_gpio_input[2] = m_singlechip_data_msg.inputdi().di2();
+//					p_response->m_gpio_input[3] = m_singlechip_data_msg.inputdi().di3();
+//					p_response->m_gpio_input[4] = m_singlechip_data_msg.inputdi().di4();
+//					p_response->m_gpio_input[5] = m_singlechip_data_msg.inputdi().di5();
+//					p_response->m_gpio_input[6] = m_singlechip_data_msg.inputdi().di6();
+//					p_response->m_gpio_input[7] = m_singlechip_data_msg.inputdi().di7();
+//					p_response->m_gpio_input[8] = m_singlechip_data_msg.inputdi().di8();
+//					p_response->m_gpio_input[9] = m_singlechip_data_msg.inputdi().di9();
+//					p_response->m_gpio_input[10] = m_singlechip_data_msg.inputdi().di10();
+//					p_response->m_gpio_input[11] = m_singlechip_data_msg.inputdi().di11();
+//					p_response->m_gpio_input[12] = m_singlechip_data_msg.inputdi().di12();
+//					p_response->m_gpio_input[13] = m_singlechip_data_msg.inputdi().di13();
+//					p_response->m_gpio_input[14] = m_singlechip_data_msg.inputdi().di14();
+//					p_response->m_gpio_input[15] = m_singlechip_data_msg.inputdi().di15();
+
+					if ( m_singlechip_direction ==1 )
+					{
+						p_response->m_outside_door_status = m_in_mcpu_statu.door_statu()-1;
+						p_response->m_over_border_status = m_in_mcpu_statu.back_io()-1;
+						p_response->m_inside_existence_flag = m_in_mcpu_statu.is_occupy()-1;
+						p_response->m_car_height_status_current = m_in_mcpu_statu.heighth()-1;
+					}
+					else if(m_singlechip_direction ==2)
+					{
+						p_response->m_outside_door_status = m_out_mcpu_statu.door_statu()-1;
+						p_response->m_inside_existence_flag = m_out_mcpu_statu.outside_safety()-1;
+					}
+				}
+
+				m_singlechip_data_msg_updata_flag = false;
+			}
+
+
+			//判断超时
+			{
+				std::unique_lock<std::mutex> t_lock3(m_lock);
+				if (std::chrono::system_clock::now() - m_singlechip_data_msg_updata_time > std::chrono::seconds(5))
+				{
+					m_dispatch_singlechip_status = DISPATCH_SINGLECHIP_DISCONNECT;
+				}
+				else
+				{
+					m_dispatch_singlechip_status = DISPATCH_SINGLECHIP_READY;
+				}
+			}
+		}
+
+	}
+}
+

+ 85 - 0
plc调度节点/dispatch/dispatch_singlechip.h

@@ -0,0 +1,85 @@
+//
+// Created by huli on 2021/11/18.
+//
+
+#ifndef NNXX_TESTS_DISPATCH_SINGLECHIP_H
+#define NNXX_TESTS_DISPATCH_SINGLECHIP_H
+
+#include "../error_code/error_code.h"
+#include <glog/logging.h>
+#include <thread>
+#include <mutex>
+#include "../tool/thread_condition.h"
+#include "../tool/common_data.h"
+#include "../tool/time_tool.h"
+#include "../task/task_base.h"
+//#include "../message/dispatch_message.pb.h"
+//#include "../message/singlechip_msg.pb.h"
+#include "../message/message.pb.h"
+#include "../dispatch/dispatch_communication.h"
+
+//调度单片机通信
+class Dispatch_singlechip
+{
+public:
+	//调度plc状态
+	enum Dispatch_singlechip_status
+	{
+		DISPATCH_SINGLECHIP_UNKNOW               	= 0,    //未知
+		DISPATCH_SINGLECHIP_READY               	= 1,    //准备,待机
+
+		DISPATCH_SINGLECHIP_FAULT					= 10,	//故障
+		DISPATCH_SINGLECHIP_DISCONNECT			= 11, 	//断连
+
+	};
+public:
+	Dispatch_singlechip();
+	Dispatch_singlechip(const Dispatch_singlechip& other)= default;
+	Dispatch_singlechip& operator =(const Dispatch_singlechip& other)= default;
+	~Dispatch_singlechip();
+public://API functions
+	//调度单片机 初始化,  单片机id, 0或者1, 单片机方向, 1是入口, 2是出口
+	Error_manager dispatch_singlechip_init(int plc_id, int singlechip_id, int singlechip_direction);
+	//调度单片机 反初始化
+	Error_manager dispatch_singlechip_uninit();
+	//调度单片机 执行状态消息
+//	Error_manager execute_for_singlechip_data_msg(message::Singlechip_data &singlechip_data_msg, bool validity);
+	//调度单片机 执行状态消息
+	Error_manager execute_for_singlechip_data_msg_new(in_mcpu_statu &t_in_mcpu_statu, bool validity);
+	//调度单片机 执行状态消息
+	Error_manager execute_for_singlechip_data_msg_new(out_mcpu_statu &t_out_mcpu_statu, bool validity);
+	//判断出口是否空闲
+	bool is_outlet_ready();
+
+public://get or set member variable
+	Dispatch_singlechip_status get_dispatch_singlechip_status();
+protected://member functions
+	//执行外界任务的执行函数
+	void execute_thread_fun();
+protected://member variable
+	std::atomic<Dispatch_singlechip_status>				m_dispatch_singlechip_status;//调度单片机的状态
+
+
+	int 										m_plc_id;					//设备id, 索引, 就是楚天车库的单元号.
+	int 										m_singlechip_id;			//单片机id, 0或者1
+	int 										m_singlechip_direction;		//单片机方向, 1是入口, 2是出口
+	std::mutex									m_lock;	//锁
+
+	//任务执行线程
+	std::thread*        						mp_execute_thread;   			//执行的线程指针,内存由本类管理
+	Thread_condition							m_execute_condition;			//执行的条件变量
+
+	//数据缓存
+//	message::Singlechip_data 						m_singlechip_data_msg;		//旧版单片机消息
+	in_mcpu_statu 									m_in_mcpu_statu;		//新版入口单片机消息
+	out_mcpu_statu 									m_out_mcpu_statu;		//新版出口单片机消息
+	bool 											m_validity;					//有效性
+	std::chrono::system_clock::time_point			m_singlechip_data_msg_updata_time;	//状态更新时间点
+	std::atomic<bool>								m_singlechip_data_msg_updata_flag;
+
+private:
+
+};
+
+
+#endif //NNXX_TESTS_DISPATCH_SINGLECHIP_H

+ 387 - 0
plc调度节点/error_code/error_code.cpp

@@ -0,0 +1,387 @@
+
+//Error_code是错误码的底层通用模块,
+//功能:用作故障分析和处理。
+
+//用法:所有的功能接口函数return错误管理类,
+//然后上层判断分析错误码,并进行故障处理。
+
+
+
+#include "error_code.h"
+
+/////////////////////////////////////////////
+//构造函数
+Error_manager::Error_manager()
+{
+    m_error_code = SUCCESS;
+    m_error_level = NORMAL;
+}
+//拷贝构造
+Error_manager::Error_manager(const Error_manager & error_manager)
+{
+    this->m_error_code = error_manager.m_error_code;
+    this->m_error_level = error_manager.m_error_level;
+	this->m_error_description=error_manager.m_error_description;
+    return ;
+}
+//赋值构造
+Error_manager::Error_manager(Error_code error_code, Error_level error_level,
+    const char* p_error_description)
+{
+    m_error_code = error_code;
+    m_error_level = error_level;
+    if(p_error_description!= nullptr)
+	{
+		m_error_description=std::string(p_error_description);
+	}
+	return ;
+}
+//赋值构造
+Error_manager::Error_manager(Error_code error_code, Error_level error_level , std::string   error_aggregate_string)
+{
+    m_error_code = error_code;
+    m_error_level = error_level;
+    m_error_description=error_aggregate_string;
+	return ;
+}
+//析构函数
+Error_manager::~Error_manager()
+{
+}
+
+//初始化
+void Error_manager::error_manager_init()
+{
+    error_manager_clear_all();
+    return;
+}
+void Error_manager::error_manager_init(Error_code error_code, Error_level error_level, const char* p_error_description)
+{
+    m_error_code = error_code;
+    m_error_level = error_level;
+	if(p_error_description!= nullptr)
+	{
+		m_error_description=std::string(p_error_description);
+	}
+	return ;
+}
+//初始化
+void Error_manager::error_manager_init(Error_code error_code, Error_level error_level , std::string error_aggregate_string)
+{
+    m_error_code = error_code;
+    m_error_level = error_level;
+    m_error_description=error_aggregate_string;
+    return ;
+}
+//重置
+void Error_manager::error_manager_reset(Error_code error_code, Error_level error_level, const char* p_error_description)
+{
+    m_error_code = error_code;
+    m_error_level = error_level;
+	if(p_error_description!= nullptr)
+	{
+		m_error_description=std::string(p_error_description);
+	}
+	return ;
+}
+//重置
+void Error_manager::error_manager_reset(Error_code error_code, Error_level error_level , std::string error_aggregate_string)
+{
+    m_error_code = error_code;
+    m_error_level = error_level;
+    m_error_description=error_aggregate_string;
+	return;
+}
+//重置
+void Error_manager::error_manager_reset(const Error_manager & error_manager)
+{
+    this->m_error_code = error_manager.m_error_code;
+    this->m_error_level = error_manager.m_error_level;
+	this->m_error_description=error_manager.m_error_description;
+    return ;
+}
+//清除所有内容
+void Error_manager::error_manager_clear_all()
+{
+    m_error_code = SUCCESS;
+    m_error_level = NORMAL;
+	m_error_description.clear();
+	return;
+}
+
+//重载=
+Error_manager& Error_manager::operator=(const Error_manager & error_manager)
+{
+    error_manager_reset(error_manager);
+	return *this;
+}
+//重载=,支持Error_manager和Error_code的直接转化,会清空错误等级和描述
+Error_manager& Error_manager::operator=(Error_code error_code)
+{
+    error_manager_clear_all();
+    set_error_code(error_code);
+	return *this;
+}
+//重载==
+bool Error_manager::operator==(const Error_manager & error_manager)
+{
+	return is_equal_error_manager(error_manager);
+}
+//重载==,支持Error_manager和Error_code的直接比较
+bool Error_manager::operator==(Error_code error_code)
+{
+    if(m_error_code == error_code)
+    {
+        return true;
+    }
+    else
+    {
+        return false;
+    }
+}
+
+//重载!=
+bool Error_manager::operator!=(const Error_manager & error_manager)
+{
+	return (! is_equal_error_manager(error_manager));
+}
+//重载!=,支持Error_manager和Error_code的直接比较
+bool Error_manager::operator!=(Error_code error_code)
+{
+    if(m_error_code != error_code)
+    {
+        return true;
+    }
+    else
+    {
+        return false;
+    }
+}
+//重载<<,支持cout<<
+std::ostream & operator<<(std::ostream &out, Error_manager &error_manager)
+{
+	out << error_manager.to_string();
+	return out;
+}
+
+//获取错误码
+Error_code Error_manager::get_error_code()
+{
+    return m_error_code;
+}
+//获取错误等级
+Error_level Error_manager::get_error_level()
+{
+    return m_error_level;
+}
+//获取错误描述的指针,(浅拷贝)
+std::string Error_manager::get_error_description()
+{
+    return m_error_description;
+}
+
+//复制错误描述,(深拷贝)
+//output:p_error_description     错误描述的字符串指针,不可以为NULL,必须要有实际的内存
+//output:description_length      错误描述的字符串长度,不可以为0,长度最好足够大,一般256即可。
+void Error_manager::copy_error_description(const char* p_error_description)
+{
+    if(p_error_description != NULL)
+    {
+        m_error_description=std::string(p_error_description);
+    }
+	return;
+}
+//复制错误描述,(深拷贝)
+//output:error_description_string     错误描述的string
+void Error_manager::copy_error_description(std::string error_description_string)
+{
+    m_error_description=error_description_string;
+	return;
+}
+
+//设置错误码
+void Error_manager::set_error_code(Error_code error_code)
+{
+    m_error_code = error_code;
+    return;
+}
+//比较错误等级并升级,取高等级的结果
+void Error_manager::set_error_level_up(Error_level error_level)
+{
+    if(m_error_level < error_level)
+    {
+        m_error_level = error_level;
+    }
+    return;
+}
+//比较错误等级并降级,取低等级的结果
+void Error_manager::set_error_level_down(Error_level error_level)
+{
+    if(m_error_level > error_level)
+    {
+        m_error_level = error_level;
+    }
+    return;
+}
+//错误等级,设定到固定值
+void Error_manager::set_error_level_location(Error_level error_level)
+{
+    m_error_level = error_level;
+    return;
+}
+//设置错误描述
+void Error_manager::set_error_description(const char* p_error_description)
+{
+	if(p_error_description != NULL)
+	{
+		m_error_description=std::string(p_error_description);
+	}
+	return;
+}
+//设置错误描述
+void Error_manager::set_error_description(std::string error_description_string)
+{
+	m_error_description = error_description_string;
+	return ;
+}
+
+//尾部追加错误描述
+void Error_manager::add_error_description(const char* p_error_description)
+{
+    if(p_error_description !=NULL)
+    {
+        m_error_description+=std::string(p_error_description);
+    }
+}
+//尾部追加错误描述
+void Error_manager::add_error_description(std::string error_description_string)
+{
+    m_error_description+=error_description_string;
+}
+
+//比较错误是否相同,
+// 注:只比较错误码和等级
+bool Error_manager::is_equal_error_manager(const Error_manager & error_manager)
+{
+    if(this->m_error_code == error_manager.m_error_code
+       && this->m_error_level == error_manager.m_error_level)
+    {
+        return true;
+    }
+    else
+    {
+        return false;
+    }
+}
+//比较并覆盖错误,讲低级错误转为字符串存放于描述中,
+//如果错误相同,则保留this的,将输入参数转入描述。
+void Error_manager::compare_and_cover_error(const Error_manager & error_manager)
+{
+    if(this->m_error_code == SUCCESS)
+    {
+        error_manager_reset(error_manager);
+    }
+    else if (error_manager.m_error_code == SUCCESS)
+    {
+		return;
+    }
+    else
+    {
+        Error_manager t_error_manager_new;
+        std::string pt_string_inside ;
+        if(this->m_error_level < error_manager.m_error_level)
+        {
+            translate_error_to_string(pt_string_inside);
+            error_manager_reset(error_manager);
+            add_error_description(pt_string_inside);
+        }
+        else
+        {
+			((Error_manager&)error_manager).translate_error_to_string(pt_string_inside);
+            add_error_description(pt_string_inside);
+        }
+    }
+	return;
+}
+//比较并覆盖错误,讲低级错误转为字符串存放于描述中,
+//如果错误相同,则保留this的,将输入参数转入描述。
+void Error_manager::compare_and_cover_error( Error_manager * p_error_manager)
+{
+	if(this->m_error_code == SUCCESS)
+	{
+		error_manager_reset(*p_error_manager);
+	}
+	else if (p_error_manager->m_error_code == SUCCESS)
+	{
+		return;
+	}
+	else
+	{
+		Error_manager t_error_manager_new;
+		std::string pt_string_inside;
+		if(this->m_error_level < p_error_manager->m_error_level)
+		{
+			translate_error_to_string(pt_string_inside);
+			error_manager_reset(*p_error_manager);
+			add_error_description(pt_string_inside);
+		}
+		else
+		{
+			p_error_manager->translate_error_to_string(pt_string_inside);
+			add_error_description(pt_string_inside);
+		}
+	}
+}
+
+
+//output:error_description_string     错误汇总的string
+void Error_manager::translate_error_to_string(std::string error_aggregate_string)
+{
+    char t_string_array[255] = {0};
+    sprintf(t_string_array, "error_code:0x%08x, error_level:%02d, error_description:",
+            m_error_code , m_error_level);
+
+    error_aggregate_string = t_string_array ;
+	error_aggregate_string+= m_error_description;
+	return;
+}
+//错误码转字符串的简易版,可支持cout<<
+//return     错误汇总的string
+std::string Error_manager::to_string()
+{
+	char t_string_array[255] = {0};
+	sprintf(t_string_array, "error_code:0x%08x, error_level:%02d, error_description:",
+            m_error_code , m_error_level);
+    std::string error_aggregate_string = t_string_array ;
+	error_aggregate_string+= m_error_description;
+	return error_aggregate_string;
+}
+
+
+
+
+//释放错误描述的内存,
+void Error_manager::free_description()
+{
+}
+
+//重新分配错误描述的内存,并从外部拷贝新的(深拷贝)
+//input:p_error_description     错误描述的字符串指针,可以为NULL,
+//input:description_length      错误描述的字符串长度,如果为0,则从p_error_description里面获取有效的长度
+void Error_manager::reallocate_memory_and_copy_string(const char* p_error_description, int description_length)
+{
+    return;
+}
+
+
+//重新分配错误描述的内存,并从外部拷贝新的(深拷贝)
+//input:error_aggregate_string     错误描述的string
+void Error_manager::reallocate_memory_and_copy_string(std::string error_aggregate_string)
+{
+    return;
+}
+
+
+
+
+

+ 777 - 0
plc调度节点/error_code/error_code.h

@@ -0,0 +1,777 @@
+
+//20211125
+
+//#define MAIN_TEST 1
+//#define PROCESS_TEST 1
+//#define TIME_TEST 1
+
+#define PLC_S7_COMMUNICATION 1	//是否开启plc的通信, 1:开启和plc的通信, 注释:关闭和plc的通信
+#define WAIT_PLC_RESPONSE 1		//是否等待plc的答复, 1:等待plc的答复, 注释:不等待plc的答复,直接向主控返回成功
+//#define MEASURE_TO_PLC_CORRECTION 1		//修正感测数据, 1:对感测数据进行修正, 注释:不修改感测数据.由感测模块去调整
+//#define PLC_OVER_TIME_TO_ERROR 1		//在等待plc的答复时, 是否超时报错, 1:超时报错, 注释:即使超时也要无限等待,直到plc的答复(可能正常完成或者异常完成)
+
+//#define COUT_SQL_STRING 1		//是否开启 sql语句的打印
+
+
+//Error_code是错误码的底层通用模块,
+//功能:用作故障分析和处理。
+
+//用法:所有的功能接口函数return错误管理类,
+//然后上层判断分析错误码,并进行故障处理。
+
+
+
+#ifndef TEST_ERROR_ERROR_CODE_H
+#define TEST_ERROR_ERROR_CODE_H
+
+#include <string>
+#include <string.h>
+#include<iostream>
+
+//错误管理类转化为字符串 的前缀,固定长度为58
+//这个是由显示格式来确定的,如果要修改格式或者 Error_code长度超过8位,Error_level长度超过2位,折需要重新计算
+#define ERROR_NAMAGER_TO_STRING_FRONT_LENGTH   58
+
+//进程加锁的状态,
+enum Lock_status
+{
+    UNLOCK      = 0,
+    LOCK        = 1,
+};
+
+//设备使能状态,
+enum Able_status
+{
+    UNABLE      = 0,
+    ENABLE      = 1,
+};
+
+//数据是否为空
+enum Empty_status
+{
+    NON_EMPTY   = 0,
+    EMPTY       = 1,
+};
+
+
+//错误码的枚举,用来做故障分析
+enum Error_code
+{
+    //成功,没有错误,默认值0
+    SUCCESS                         = 0x00000000,
+
+
+    //基本错误码,
+    ERROR                           = 0x00000001,//错误
+    PARTIAL_SUCCESS                 = 0x00000002,//部分成功
+    WARNING                         = 0x00000003,//警告
+    FAILED                          = 0x00000004,//失败
+
+    NODATA                          = 0x00000010,//没有数据,传入参数容器内部没有数据时,
+	INVALID_MESSAGE					= 0x00000011, //无效的消息,
+	PARSE_FAILED					= 0x00000012,//解析失败
+
+    PAUSE                           = 0x00000013,   //急停
+    TASK_CANCEL                     = 0x00000014,   //任务取消
+
+    DISCONNECT                      = 0x00000020,   //通讯中断/断开连接
+    UNKNOW_STATU                    = 0x00000021,   //未知状态
+
+    TASK_TIMEOVER					= 0x00000020,//任务超时
+	RESPONSE_TIMEOUT                = 0x00000021,//答复超时
+
+    POINTER_IS_NULL                 = 0x00000101,//空指针
+    PARAMETER_ERROR                 = 0x00000102,//参数错误,传入参数不符合规范时,
+    POINTER_MALLOC_FAIL             = 0x00000103,//手动分配内存失败
+
+    CLASS_BASE_FUNCTION_CANNOT_USE  = 0x00000201,//基类函数不允许使用,必须使用子类的
+
+	CONTAINER_IS_TERMINATE			= 0x00000301,//容器被终止
+
+
+
+
+//    错误码的规范,
+//    错误码是int型,32位,十六进制。
+//    例如0x12345678
+//    12表示功能模块,例如:laser雷达模块               	框架制定
+//    34表示文件名称,例如:laser_livox.cpp             框架制定
+//    56表示具体的类,例如:class laser_livox           个人制定
+//    78表示类的函数,例如:laser_livox::start();       个人制定
+//    注:错误码的制定从1开始,不要从0开始,
+//        0用作错误码的基数,用来位运算,来判断错误码的范围。
+
+
+
+
+
+
+
+//    laser扫描模块
+    LASER_ERROR_BASE                = 0x01000000,
+
+//    laser_base基类
+	LASER_BASE_ERROR_BASE			= 0x01010000,
+    LASER_TASK_PARAMETER_ERROR      = 0x01010001,   //雷达基类模块, 任务输入参数错误
+    LASER_CONNECT_FAILED,							//雷达基类模块, 连接失败
+	LASER_START_FAILED,								//雷达基类模块, 开始扫描失败
+	LASER_CHECK_FAILED,								//雷达基类模块, 检查失败
+	LASER_STATUS_BUSY,								//雷达基类模块, 状态正忙
+	LASER_STATUS_ERROR,								//雷达基类模块, 状态错误
+	LASER_TASK_OVER_TIME,							//雷达基类模块, 任务超时
+	LASER_QUEUE_ERROR,								//雷达基类模块, 数据缓存错误
+
+
+//   livox  大疆雷达
+    LIVOX_ERROR_BASE                = 0x01020000,
+    LIVOX_START_FAILE,								//livox模块,开始扫描失败
+	LIVOX_TASK_TYPE_ERROR,							//livox模块,任务类型错误
+	lIVOX_CANNOT_PUSH_DATA,							//livox模块,不能添加扫描的数据
+	lIVOX_CHECK_FAILED,								//livox模块,检查失败
+	lIVOX_STATUS_BUSY,								//livox模块,状态正忙
+	lIVOX_STATUS_ERROR,								//livox模块,状态错误
+
+	//laser_manager 雷达管理模块
+	LASER_MANAGER_ERROR_BASE						= 0x01030000,
+	LASER_MANAGER_READ_PROTOBUF_ERROR,				//雷达管理模块,读取参数错误
+	LASER_MANAGER_STATUS_BUSY,						//雷达管理模块,状态正忙
+	LASER_MANAGER_STATUS_ERROR,						//雷达管理模块,状态错误
+	LASER_MANAGER_TASK_TYPE_ERROR,					//雷达管理模块,任务类型错误
+	LASER_MANAGER_IS_NOT_READY,						//雷达管理模块,不在准备状态
+	LASER_MANAGER_TASK_OVER_TIME,					//雷达管理模块,任务超时
+	LASER_MANAGER_LASER_INDEX_ERRPR,				//雷达管理模块,雷达索引错误,编号错误。
+	LASER_MANAGER_LASER_INDEX_REPEAT,				//雷达管理模块,需要扫描的雷达索引重复,可忽略的错误,提示作用
+
+//livox_driver 雷达livox驱动模块
+	LIVOX_DRIVER_ERROR_BASE							= 0x01040000,
+	LIVOX_DRIVER_SN_REPEAT,							//livox驱动模块, 雷达广播码重复
+	LIVOX_DRIVER_SN_ERROR,							//livox驱动模块, 雷达广播码错误
+	LIVOX_SKD_INIT_FAILED,							//livox驱动模块, livox_sdk初始化失败
+	LIVOX_DRIVER_NOT_READY,							//livox驱动模块, livox没有准备好.
+
+
+
+
+     //PLC error code  ...
+    PLC_ERROR_BASE                  				= 0x02010000,
+    PLC_UNKNOWN_ERROR,								//plc未知错误
+    PLC_EMPTY_TASK,									//plc任务为空
+    PLC_IP_PORT_ERROR,								//plc的ip端口错误
+    PLC_SLAVE_ID_ERROR,								//plc的身份id错误
+    PLC_CONNECTION_FAILED,							//PLC连接失败
+    PLC_READ_FAILED,								//plc读取失败
+    PLC_WRITE_FAILED,								//plc写入失败
+    PLC_NOT_ENOUGH_DATA_ERROR,						//PLC没有足够的数据错误
+
+
+
+    //locate 定位模块,
+	LOCATER_ERROR_BASE                				= 0x03000000,
+	//LASER_MANAGER 定位管理模块
+	LOCATER_MANAGER_ERROR_BASE                		= 0x03010000,
+	LOCATER_MANAGER_READ_PROTOBUF_ERROR,				//定位管理模块,读取参数错误
+	LOCATER_MANAGER_STATUS_BUSY,						//定位管理模块,状态正忙
+	LOCATER_MANAGER_STATUS_ERROR,						//定位管理模块,状态错误
+	LOCATER_MANAGER_TASK_TYPE_ERROR,					//定位管理模块,任务类型错误
+	LOCATER_MANAGER_IS_NOT_READY,						//定位管理模块,不在准备状态
+	LOCATER_MANAGER_CLOUD_MAP_ERROR,					//定位管理模块,任务输入点云map的error
+	LOCATER_MANAGER_TASK_OVER_TIME,						//定位管理模块,任务超时
+
+
+	//Locater  算法模块	
+	LOCATER_ALGORITHM_ERROR_BASE					= 0x03020000,
+	LOCATER_TASK_INIT_CLOUD_EMPTY,						//定位任务初始化点云为空
+	LOCATER_TASK_ERROR,									//定位任务错误
+	LOCATER_TASK_INPUT_CLOUD_UNINIT,					//定位任务输入点云为空
+	LOCATER_INPUT_CLOUD_EMPTY,							//定位输入点云为空
+	LOCATER_YOLO_UNINIT,								//定位yolo未初始化
+	LOCATER_POINTSIFT_UNINIT,							//定位POINTSIFT未初始化
+	LOCATER_3DCNN_UNINIT,								//定位3DCNN未初始化
+	LOCATER_INPUT_YOLO_CLOUD_EMPTY,						//定位输入yolo点云为空
+	LOCATER_Y_OUT_RANGE_BY_PLC,							//定位超出plc的限制范围
+	LOCATER_MEASURE_HEIGHT_CLOUD_UNINIT,				//定位测量高点云未初始化
+	LOCATER_MEASURE_HEIGHT_CLOUD_EMPTY,					//定位测量高点云为空
+	LOCATER_INPUT_CLOUD_UNINIT,							//定位输入点云未初始化
+
+
+    //point sift from 0x03010100-0x030101FF
+	LOCATER_SIFT_ERROR_BASE							=0x03020100,
+   	LOCATER_SIFT_INIT_FAILED,							//定位过滤模块,初始化失败
+    LOCATER_SIFT_INPUT_CLOUD_UNINIT,					//定位过滤模块,输入点云未初始化
+	LOCATER_SIFT_INPUT_CLOUD_EMPTY,						//定位过滤模块,输入点云为空
+	LOCATER_SIFT_GRID_ERROR,							//定位过滤模块,筛选网格错误
+	LOCATER_SIFT_SELECT_ERROR,							//定位过滤模块,筛选选择错误
+	LOCATER_SIFT_CLOUD_VERY_LITTLE,						//定位过滤模块,筛选点云很少
+	LOCATER_SIFT_CREATE_INPUT_DATA_FAILED,				//定位过滤模块,筛选创建输入数据失败
+	LOCATER_SIFT_PREDICT_FAILED,						//定位过滤模块,预测失败
+	LOCATER_SIFT_PREDICT_TIMEOUT,						//定位过滤模块,预测超时
+	LOCATER_SIFT_PREDICT_NO_WHEEL_POINT,				//定位过滤模块,预测结果没有车轮点云
+	LOCATER_SIFT_PREDICT_NO_CAR_POINT,					//定位过滤模块,预测结果没有车身点云
+
+    LOCATER_SIFT_FILTE_OBS_FAILED,						//定位过滤模块,过滤OBS失败
+    LOCATER_SIFT_INPUT_BOX_PARAMETER_FAILED,			//定位过滤模块,输入范围参数错误
+
+//    //yolo 
+//    LOCATER_YOLO_ERROR_BASE						=0x03020200,
+//    LOCATER_YOLO_DETECT_FAILED,
+//    LOCATER_YOLO_DETECT_NO_TARGET,
+//    LOCATER_YOLO_PARAMETER_INVALID,
+//    LOCATER_YOLO_INPUT_CLOUD_UNINIT,
+
+    //3dcnn from 0x03010300-0x030103FF
+    LOCATER_3DCNN_ERROR_BASE						=0x03020300,
+    LOCATER_3DCNN_INIT_FAILED,							//定位3DCNN模块,初始化失败
+    LOCATER_3DCNN_INPUT_CLOUD_UNINIT,					//定位3DCNN模块,输入点云未初始化
+	LOCATER_3DCNN_INPUT_CLOUD_EMPTY,					//定位3DCNN模块,输入点云为空
+	LOCATER_3DCNN_INPUT_CLOUD_MAP_ERROR,				//定位3DCNN模块,输入点云的map错误
+	LOCATER_3DCNN_PCA_OUT_ERROR,						//定位3DCNN模块,pca错误
+	LOCATER_3DCNN_EXTRACT_RECT_ERROR,					//定位3DCNN模块,提取矩形错误
+	LOCATER_3DCNN_RECT_SIZE_ERROR,						//定位3DCNN模块,矩形范围错误
+
+    LOCATER_3DCNN_PREDICT_FAILED,						//定位3DCNN模块,预测失败
+    LOCATER_3DCNN_VERIFY_RECT_FAILED_3,					//定位3DCNN模块,验证矩形失败3
+    LOCATER_3DCNN_VERIFY_RECT_FAILED_4,					//定位3DCNN模块,验证矩形失败4
+    LOCATER_3DCNN_KMEANS_FAILED,						//定位3DCNN模块,k均值失败
+    LOCATER_3DCNN_IIU_FAILED,							//定位3DCNN模块,IIU失败
+    LOCATER_3DCNN_PCA_OUT_CLOUD_EMPTY,					//定位3DCNN模块,pca输出点云为空
+
+	//感测和主控通信
+	LOCATER_MSG_TABLE_NOT_EXIST  				= 0x03030100,
+    LOCATER_MSG_RESPONSE_TYPE_ERROR,                                //测量反馈消息类型错误(致命)
+    LOCATER_MSG_RESPONSE_INFO_ERROR,
+    LOCATER_MSG_REQUEST_CANCELED,
+    LOCATER_MSG_REQUEST_INVALID,
+    LOCATER_MSG_RESPONSE_HAS_NO_REQUEST,
+    LOCATER_MSG_REQUEST_REPEATED,
+
+    //System_manager error from 0x04010000-0x0401FFFF
+    SYSTEM_READ_PARAMETER_ERROR						=0x04010100,
+    SYSTEM_PARAMETER_ERROR,
+    SYSTEM_INPUT_TERMINOR_NO_LASERS,
+
+    //terminor_command_executor.cpp from 0x04010200-0x040102FF
+    TERMINOR_NOT_READY								=0x04010200,
+    TERMINOR_INPUT_LASER_NULL,
+    TERMINOR_NOT_CONTAINS_LASER,
+    TERMINOR_INPUT_PLC_NULL,
+    TERMINOR_INPUT_LOCATER_NULL,
+    TERMINOR_CREATE_WORKING_THREAD_FAILED,
+    TERMINOR_FORCE_QUIT,
+    TERMINOR_LASER_TIMEOUT,
+    TERMINOR_POST_PLC_TIMEOUT,
+    TERMINOR_CHECK_RESULTS_ERROR,
+
+    ////Hardware limit from 0x05010000 - 0x0501ffff
+    ///railing.cpp from 0x05010100-0x050101ff
+    HARDWARE_LIMIT_LEFT_RAILING						=0x05010100,         //左栏杆限制
+    HARDWARE_LIMIT_RAILING_PARAMETER_ERROR,
+    HARDWARE_LIMIT_RAILING_ERROR,
+    HARDWARE_LIMIT_CENTER_X_LEFT,
+    HARDWARE_LIMIT_CENTER_X_RIGHT,
+    HARDWARE_LIMIT_CENTER_Y_TOP,
+    HARDWARE_LIMIT_CENTER_Y_BOTTOM,
+    HARDWARE_LIMIT_HEIGHT_OUT_RANGE,
+    HARDWARE_LIMIT_ANGLE_OUT_RANGE,
+    //termonal_limit from 0x05010200-0x050102ff
+    HARDWARE_LIMIT_TERMINAL_LEFT_ERROR,
+    HARDWARE_LIMIT_TERMINAL_RIGHT_ERROR,
+    HARDWARE_LIMIT_TERMINAL_LR_ERROR,
+
+
+//万集设备模块,
+    WANJI_LIDAR_DEVICE_ERROR_BASE								=0x06080000,//万集设备模块,错误基类
+	WANJI_LIDAR_DEVICE_STATUS_BUSY,									//万集设备模块,状态正忙
+	WANJI_LIDAR_DEVICE_STATUS_ERROR,								//万集设备模块,状态错误
+	WANJI_LIDAR_DEVICE_TASK_TYPE_ERROR,								//万集设备模块,任务类型错误
+	WANJI_LIDAR_DEVICE_TASK_OVER_TIME,								//万集设备模块,任务超时
+	WANJI_LIDAR_DEVICE_NO_CLOUD,									//万集设备模块,没有点云
+    // velodyne设备模块
+    VELODYNE_LIDAR_DEVICE_ERROR_BASE,								//velodyne设备模块,错误基类
+    VELODYNE_LIDAR_DEVICE_STATUS_BUSY,									//velodyne设备模块,状态正忙
+	VELODYNE_LIDAR_DEVICE_STATUS_ERROR,								//velodyne设备模块,状态错误
+	VELODYNE_LIDAR_DEVICE_TASK_TYPE_ERROR,								//velodyne设备模块,任务类型错误
+	VELODYNE_LIDAR_DEVICE_TASK_OVER_TIME,								//velodyne设备模块,任务超时
+	VELODYNE_LIDAR_DEVICE_NO_CLOUD,									//velodyne设备模块,没有点云
+
+
+	//万集通信wj_lidar error from 0x06010000-0x0601FFFF
+	WJ_LIDAR_COMMUNICATION_ERROR_BASE				=0x06010000,
+	WJ_LIDAR_COMMUNICATION_UNINITIALIZED,							//万集通信,未初始化
+	WJ_LIDAR_COMMUNICATION_DISCONNECT,								//万集通信,断连
+	WJ_LIDAR_COMMUNICATION_FAULT,									//万集通信,故障
+	WJ_LIDAR_CONNECT_FAILED,										//万集通信,连接失败
+    WJ_LIDAR_UNINITIALIZED,											//万集通信,未初始化
+    WJ_LIDAR_READ_FAILED,											//万集通信,读取失败
+    WJ_LIDAR_WRITE_FAILED,											//万集通信,写入失败
+    WJ_LIDAR_GET_CLOUD_TIMEOUT,										//万集通信,获取点云超时
+    // velodyne通信
+    VELODYNE_LIDAR_COMMUNICATION_UNINITIALIZED,							//velodyne通信,未初始化
+	VELODYNE_LIDAR_COMMUNICATION_DISCONNECT,								//velodyne通信,断连
+	VELODYNE_LIDAR_COMMUNICATION_FAULT,									//velodyne通信,故障
+	VELODYNE_LIDAR_CONNECT_FAILED,										//velodyne通信,连接失败
+    VELODYNE_LIDAR_UNINITIALIZED,											//velodyne通信,未初始化
+    VELODYNE_LIDAR_READ_FAILED,											//velodyne通信,读取失败
+    VELODYNE_LIDAR_WRITE_FAILED,											//velodyne通信,写入失败
+    VELODYNE_LIDAR_GET_CLOUD_TIMEOUT,										//velodyne通信,获取点云超时
+
+    //万集解析 wj lidar protocol error from 0x06020000-0x0602FFFF
+        WJ_PROTOCOL_ERROR_BASE						=0x06020000,
+	WJ_PROTOCOL_STATUS_BUSY,										//万集解析, 状态正忙
+	WJ_PROTOCOL_STATUS_ERROR,										//万集解析, 状态错误
+    WJ_PROTOCOL_INTEGRITY_ERROR,									//万集解析, 完整性错误								
+    WJ_PROTOCOL_PARSE_FAILED,										//万集解析, 解析失败
+    WJ_PROTOCOL_EMPTY_PACKAGE,										//万集解析, 空包
+    WJ_PROTOCOL_EXCEED_MAX_SIZE,									//万集解析, 超出最大范围
+
+    //万集测量范围 wj region detect error from 0x06030000-0x0603FFFF
+	WJ_REGION_ERROR_BASE							= 0x06030000,
+	WJ_REGION_EMPTY_CLOUD,											//万集测量,空点云	
+	WJ_REGION_EMPTY_NO_WHEEL_INFORMATION,							//万集测量,没有车轮信息
+    WJ_REGION_RECTANGLE_ANGLE_ERROR,								//万集测量,矩形旋转角错误
+    WJ_REGION_RECTANGLE_SIZE_ERROR,									//万集测量,矩形大小错误
+    WJ_REGION_RECTANGLE_SYMMETRY_ERROR,								//万集测量,矩形对称错误
+    WJ_REGION_CLUSTER_SIZE_ERROR,									//万集测量,簇大小错误
+    WJ_REGION_CERES_SOLVE_ERROR,                                    //万集测量,优化失败
+    //velodyne测量范围
+	VELODYNE_REGION_ERROR_BASE,
+	VELODYNE_REGION_EMPTY_CLOUD,											//velodyne测量,空点云	
+	VELODYNE_REGION_EMPTY_NO_WHEEL_INFORMATION,							//velodyne测量,没有车轮信息
+    VELODYNE_REGION_RECTANGLE_ANGLE_ERROR,								//velodyne测量,矩形旋转角错误
+    VELODYNE_REGION_RECTANGLE_SIZE_ERROR,									//velodyne测量,矩形大小错误
+    VELODYNE_REGION_RECTANGLE_SYMMETRY_ERROR,								//velodyne测量,矩形对称错误
+    VELODYNE_REGION_CLUSTER_SIZE_ERROR,									//velodyne测量,簇大小错误
+    VELODYNE_REGION_CERES_SOLVE_ERROR,                                    //velodyne测量,优化失败
+
+    //万集管理模块 wj manager error from 0x06040000-0x0604FFFF
+	WJ_MANAGER_ERROR_BASE										= 0x06040000,
+    WJ_MANAGER_UNINITIALIZED,									//万集管理模块,未初始化
+    WJ_MANAGER_LIDAR_DISCONNECTED,								//万集管理模块,雷达断链
+    WJ_MANAGER_PLC_DISCONNECTED,								//万集管理模块,plc断链
+    WJ_MANAGER_EMPTY_CLOUD,										//万集管理模块,空点云
+	WJ_MANAGER_READ_PROTOBUF_ERROR,								//万集管理模块,读取参数错误
+	WJ_MANAGER_INIT_ERROR,										//万集管理模块,初始化error
+	WJ_MANAGER_TASK_TYPE_ERROR,									//万集管理模块,任务类型错误
+	WJ_MANAGER_STATUS_BUSY,										//万集管理模块,状态正忙
+	WJ_MANAGER_STATUS_ERROR,									//万集管理模块,状态错误
+	WJ_MANAGER_LASER_INDEX_ERRPR,								//万集管理模块,雷达索引错误,编号错误。
+	WJ_MANAGER_LASER_INDEX_REPEAT,								//万集管理模块,需要扫描的雷达索引重复,可忽略的错误,提示作用
+	WJ_MANAGER_TASK_OVER_TIME,									//万集管理模块,任务超时
+    VELODYNE_MANAGER_ERROR_BASE,										
+    VELODYNE_MANAGER_UNINITIALIZED,									//velodyne管理模块,未初始化
+    VELODYNE_MANAGER_LIDAR_DISCONNECTED,								//velodyne管理模块,雷达断链
+    VELODYNE_MANAGER_EMPTY_CLOUD,										//velodyne管理模块,空点云
+	VELODYNE_MANAGER_READ_PROTOBUF_ERROR,								//velodyne管理模块,读取参数错误
+	VELODYNE_MANAGER_INIT_ERROR,										//velodyne管理模块,初始化error
+	VELODYNE_MANAGER_TASK_TYPE_ERROR,									//velodyne管理模块,任务类型错误
+	VELODYNE_MANAGER_STATUS_BUSY,										//velodyne管理模块,状态正忙
+	VELODYNE_MANAGER_STATUS_ERROR,									//velodyne管理模块,状态错误
+	VELODYNE_MANAGER_LASER_INDEX_ERRPR,								//velodyne管理模块,雷达索引错误,编号错误。
+	VELODYNE_MANAGER_LASER_INDEX_REPEAT,								//velodyne管理模块,需要扫描的雷达索引重复,可忽略的错误,提示作用
+	VELODYNE_MANAGER_TASK_OVER_TIME,									//velodyne管理模块,任务超时
+
+//万集任务模块
+	WJ_LIDAR_TASK_ERROR_BASE									=0x06050000,
+	WJ_LIDAR_TASK_EMPTY_RESULT,									//万集任务模块,空结果
+    WJ_LIDAR_TASK_EMPTY_TASK,									//万集任务模块,空任务
+    WJ_LIDAR_TASK_WRONG_TYPE,									//万集任务模块,错误类型
+    WJ_LIDAR_TASK_INVALID_TASK,									//万集任务模块,无效任务
+    WJ_LIDAR_TASK_MEASURE_FAILED,								//万集任务模块,测量失败
+
+    // 万集滤波
+    WJ_FILTER_ERROR_BASE                                        =0x06060000,
+    WJ_FILTER_LACK_OF_RESULT,                                   //万集滤波,结果不足以进行滤波
+    WJ_FILTER_FLUCTUATING,                                      //万集滤波,结果波动过大
+
+    //task module, 任务模块  error from 0x10010000-0x1001FFFF
+	TASK_MODULE_ERROR_BASE 							= 0x10010000,
+	TASK_TYPE_IS_UNKNOW,
+	TASK_NO_RECEIVER,
+
+
+	//Communication module, 通信模块
+	COMMUNICATION_BASE_ERROR_BASE					= 0x11010000,
+	COMMUNICATION_READ_PROTOBUF_ERROR,				//模块,读取参数错误
+	COMMUNICATION_BIND_ERROR,
+	COMMUNICATION_CONNECT_ERROR,
+	COMMUNICATION_ANALYSIS_TIME_OUT,									//解析超时,
+	COMMUNICATION_EXCUTER_IS_BUSY,										//处理器正忙, 请稍等
+
+
+
+
+	//system module, 系统模块
+	SYSTEM_EXECUTOR_ERROR_BASE						= 0x12010000,		//系统执行模块,
+	SYSTEM_EXECUTOR_PARSE_ERROR,										//系统执行模块, 解析消息错误
+	SYSTEM_EXECUTOR_STATUS_BUSY,										//系统执行模块, 状态正忙
+	SYSTEM_EXECUTOR_STATUS_ERROR,										//系统执行模块, 状态错误
+	SYSTEM_EXECUTOR_CHECK_ERROR,										//系统执行模块, 检查错误
+
+
+
+	//Dispatch 调度 模块 错误码
+	DISPATCH_ERROR_BASE								= 0x13000000,
+
+	//Dispatch_manager 调度管理模块 错误码
+	DISPATCH_MANAGER_ERROR_BASE						= 0x13010000,
+	DISPATCH_MANAGER_READ_PROTOBUF_ERROR,				//调度管理模块,读取参数错误
+	DISPATCH_MANAGER_STATUS_BUSY,						//调度管理模块,状态正忙
+	DISPATCH_MANAGER_STATUS_ERROR,						//调度管理模块,状态错误
+	DISPATCH_MANAGER_TASK_TYPE_ERROR,					//调度管理模块,任务类型错误
+	DISPATCH_MANAGER_IS_NOT_READY,						//调度管理模块,不在准备状态
+	DISPATCH_MANAGER_SPACE_LOCK_ERROR,					//调度管理模块,空间锁错误
+
+
+	DISPATCH_PROCESS_ERROR_BASE								= 0x13020000,
+	DISPATCH_PROCESS_IS_NOT_READY,						//调度流程, 不在准备状态
+	DISPATCH_PROCESS_DEVICE_TYPE_ERROR,					//调度流程, 设备类型错误
+	DISPATCH_PROCESS_DEVICE_STATUS_ERROR,				//调度流程, 设备状态错误
+	DISPATCH_PROCESS_TASK_STATUS_ERROR,					//调度流程, 任务类型错误
+	DISPATCH_PROCESS_COMMAND_KEY_REPEAT,				//调度流程, 唯一码错误
+	DISPATCH_PROCESS_INIT_ERROR,						//调度流程, 初始化错误
+
+
+	DISPATCH_DEVICE_ERROR_BASE								= 0x13030000,
+	DISPATCH_DEVICE_READ_PROTOBUF_ERROR,				//调度设备模块,读取参数错误
+	DISPATCH_DEVICE_STATUS_BUSY,						//调度设备模块,状态正忙
+	DISPATCH_DEVICE_STATUS_ERROR,						//调度设备模块,状态错误
+	DISPATCH_DEVICE_STATUS_DISCONNECT,					//调度设备模块,状态断连
+	DISPATCH_DEVICE_TASK_TYPE_ERROR,					//调度设备模块,任务类型错误
+	DISPATCH_DEVICE_TASK_OVER_TIME,						//调度设备模块,任务超时
+	DISPATCH_DEVICE_TASK_REPEAT,						//调度设备模块,任务重复, 任务已经存在
+	DISPATCH_DEVICE_IS_NOT_READY,						//调度设备模块,不在准备状态
+	DISPATCH_DEVICE_RESPONS_ERROR,						//调度设备模块,指令的执行失败
+	DISPATCH_DEVICE_TASK_NOTHINGNESS,					//调度设备模块,任务不存在
+	DISPATCH_DEVICE_TASK_LEVEL_ERROR,					//调度设备模块,任务等级错误
+
+
+	CARRIER_ERROR_BASE								= 0x13040000,
+	CARRIER_READ_PROTOBUF_ERROR,				//搬运器模块,读取参数错误
+	CARRIER_STATUS_BUSY,						//搬运器模块,状态正忙
+	CARRIER_STATUS_ERROR,						//搬运器模块,状态错误
+	CARRIER_STATUS_DISCONNECT,					//搬运器模块,状态断连
+	CARRIER_TASK_TYPE_ERROR,					//搬运器模块,任务类型错误
+	CARRIER_TASK_OVER_TIME,						//搬运器模块,任务超时
+	CARRIER_IS_NOT_READY,						//搬运器模块,不在准备状态
+	CARRIER_RESPONS_ERROR,						//搬运器模块,指令的执行失败
+	CARRIER_TASK_NOTHINGNESS,					//搬运器模块,任务不存在
+	CARRIER_POSE_ERROR,							//搬运器模块,姿态错误
+	CARRIER_CONRTOL_PARAMETER_ERROR,			//搬运器模块,控制参数错误
+
+	CATCHER_ERROR_BASE								= 0x13050000,
+	CATCHER_READ_PROTOBUF_ERROR,				//抓取器模块,读取参数错误
+	CATCHER_STATUS_BUSY,						//抓取器模块,状态正忙
+	CATCHER_STATUS_ERROR,						//抓取器模块,状态错误
+	CATCHER_STATUS_DISCONNECT,					//抓取器模块,状态断连
+	CATCHER_TASK_TYPE_ERROR,					//抓取器模块,任务类型错误
+	CATCHER_TASK_OVER_TIME,						//抓取器模块,任务超时
+	CATCHER_IS_NOT_READY,						//抓取器模块,不在准备状态
+	CATCHER_RESPONS_ERROR,						//抓取器模块,指令的执行失败
+	CATCHER_TASK_NOTHINGNESS,					//抓取器模块,任务不存在
+	CATCHER_POSE_ERROR,							//抓取器模块,姿态错误
+	CATCHER_CONRTOL_PARAMETER_ERROR,			//抓取器模块,控制参数错误
+
+	PASSAGEWAY_ERROR_BASE								= 0x13060000,
+	PASSAGEWAY_READ_PROTOBUF_ERROR,				//通道口模块,读取参数错误
+	PASSAGEWAY_STATUS_BUSY,						//通道口模块,状态正忙
+	PASSAGEWAY_STATUS_ERROR,						//通道口模块,状态错误
+	PASSAGEWAY_STATUS_DISCONNECT,					//通道口模块,状态断连
+	PASSAGEWAY_TASK_TYPE_ERROR,					//通道口模块,任务类型错误
+	PASSAGEWAY_TASK_OVER_TIME,						//通道口模块,任务超时
+	PASSAGEWAY_IS_NOT_READY,						//通道口模块,不在准备状态
+	PASSAGEWAY_RESPONS_ERROR,						//通道口模块,指令的执行失败
+	PASSAGEWAY_TASK_NOTHINGNESS,					//通道口模块,任务不存在
+
+
+	//DISPATCH_COORDINATES module, 通信模块
+	DISPATCH_COORDINATES_ERROR_BASE					= 0x13060000,
+	DISPATCH_COORDINATES_READ_PROTOBUF_ERROR,				//调度坐标模块,读取参数错误
+	DISPATCH_COORDINATES_ID_ERROR,							//调度坐标模块,坐标id错误
+	DISPATCH_COORDINATES_PATH_ERROR,						//调度坐标模块,路径方向错误
+	DISPATCH_COORDINATES_CAN_NOT_LOCK,						//调度坐标模块,不能加锁
+
+	//Dispatch_plc 调度plc模块
+	DISPATCH_PLC_ERROR_BASE							= 0x13070000,
+	DISPATCH_PLC_REQUEST_ERROR,								//调度plc模块,请求错误
+	DISPATCH_PLC_RESPONS_ERROR,								//调度plc模块,指令的执行失败
+	DISPATCH_PLC_STATUS_ERROR,								//调度plc模块,状态错误
+	DISPATCH_PLC_TIME_OUT,									//调度plc模块,超时
+	DISPATCH_PLC_DIRECTION_ERROR,							//调度plc模块,方向错误
+
+	DISPATCH_PLC_REALLOCATE_MIN_CAR, 						//调度plc模块,重新分配小车
+	DISPATCH_PLC_REALLOCATE_MID_CAR, 						//调度plc模块,重新分配中车
+	DISPATCH_PLC_REALLOCATE_BIG_CAR, 						//调度plc模块,重新分配大车
+	DISPATCH_PLC_REALLOCATE_HUGE_CAR, 						//调度plc模块,重新分配fault
+	DISPATCH_PLC_REALLOCATE_FAULT_CAR, 						//调度plc模块,重新分配fault
+
+	//snap7 通信模块 错误码
+	SNAP7_ERROR_BASE								= 0x1401000,
+	SNAP7_READ_PROTOBUF_ERROR,							//snap7通信模块,读取参数错误
+	SNAP7_CONNECT_ERROR,								//snap7通信模块,连接错误
+	SNAP7_DISCONNECT_ERROR,								//snap7通信模块,断连错误
+	SNAP7_READ_ERROR,									//snap7通信模块,读取错误
+	SNAP7_WRITE_ERROR,									//snap7通信模块,写入错误
+	SNAP7_ANALYSIS_TIME_OUT,									//解析超时,
+	SNAP7_EXCUTER_IS_BUSY,										//处理器正忙, 请稍等
+	
+
+	
+	
+    
+    //parkspace allocator,车位分配模块
+    PARKSPACE_ALLOCATOR_ERROR_BASE                  = 0x20010000,     
+    PARKSPACE_ALLOCATOR_MSG_REQUEST_TYPE_ERROR,    //反馈车位消息类型错误 
+    PARKSPACE_ALLOCATOR_MSG_RESPONSE_TYPE_ERROR,    //反馈车位消息类型错误
+    PARKSPACE_ALLOCATOR_MSG_PARSE_ERROR,            //请求消息解析错误
+    PARKSPACE_ALLOCATOR_SPACE_EMPTY,                //空车位异常,车库无车位。或许由模块初始化异常产生
+    PARKSPACE_ALLOCATOR_ALLOCATE_FAILED,            //无合适车位,分配失败
+    PARKSPACE_ALLOCATOR_SEARCH_FAILED,              //未找到车辆对应车位
+    PARKSPACE_ALLOCATOR_RELEASE_FAILED,             //未找到匹配的车位,车位未释放
+    PARKSPACE_ALLOCATOR_FORCE_UPDATE_FAILED,        //手动更新失败,未找到匹配车位
+    PARKSPACE_ALLOCATOR_PARAM_ERROR,                //传入参数错误
+    PARKSPACE_ALLOCATOR_CONFIRM_ALLOC_ERROR,        //确认分配车位错误
+    PARKSPACE_ALLOCATOR_CAR_ALREADY_EXIST,          //车辆已存在
+
+    // 数据库操作
+    DB_ERROR_BASE                                   = 0x20020000,
+    DB_INIT_FAILED,									//数据库初始化失败
+    DB_CONNECT_FAILED,                              //数据库连接失败
+    DB_STATUS_ERROR,								//数据库状态错误
+	DB_MANAGER_STATUS_ERROR,						//数据库管理状态错误
+    DB_INSERT_FAILED,                               //数据库插入失败
+    DB_DELETE_FAILED,                               //数据库删除失败
+    DB_UPDATE_FAILED,                               //数据库更新失败
+    DB_QUERY_FAILED,                                //数据库查询失败
+    DB_UNINITIALIZED,                               //数据库外层未初始化
+    DB_DISCONNECTED,                                //数据库外层连接失去
+    DB_RESULT_SET_EMPTY,                            //数据库外层查询返回结果空指针
+    DB_RESULT_SET_PARSE_ERROR,                      //数据库外层查询结果解析失败
+    DB_CONNECT_CHANNEL_NOT_FOUND,					//数据库连接通道未找到
+    DB_CONNECT_CHANNEL_NUMBER_ERROR,				//数据库连接通道数量错误
+    DB_QUERY_DATA_REPEAT,							//数据库查询数据重复
+    DB_QUERY_NOT_DATA,								//数据库未查询到数据
+	DB_QUERY_DATA_FAILED,							//数据库查询数据错误
+	DB_NOT_QUERY_EMPTY_PARKSPACE,					//数据库未查询到空车位
+	DB_PROTOBUF_ERROR,								//数据库配置参数读取错误
+	DB_CONTROL_FAILED,                              //数据库控制语句失败
+	DB_QUERY_OUTLET_OCCUPY,                         //数据库 查询出口被占用
+
+
+
+
+    //parkspace error code
+    PARKSPACE_REQUEST_MSG_TYPE_ERROR            	= 0x20030000,
+    PARKSPACE_ALLOCMSG_RESPONSE_HAS_NO_REQUEST,
+    PARKSPACE_SEARCHMSG_RESPONSE_HAS_NO_REQUEST,
+    PARKSPACE_RELEASEMSG_RESPONSE_HAS_NO_REQUEST,
+    PARKSPACE_ALLOC_REQUEST_INVALID,
+    PARKSPACE_SEARCH_REQUEST_INVALID,
+    PARKSPACE_RELEASE_REQUEST_INVALID,
+
+    PARKSPACE_ALLOC_REQUEST_REPEATED,
+    PARKSPACE_SEARCH_REQUEST_REPEATED,
+    PARKSPACE_RELEASE_REQUEST_REPEATED,
+
+    PARKSPACE_ALLOC_RESPONSE_TYPE_ERROR,
+    PARKSPACE_SEARCH_RESPONSE_TYPE_ERROR,
+    PARKSPACE_RELEASE_RESPONSE_TYPE_ERROR,
+
+    PARKSPACE_ALLOC_RESPONSE_INFO_ERROR,
+    PARKSPACE_SEARCH_RESPONSE_INFO_ERROR,
+    PARKSPACE_RELEASE_RESPONSE_INFO_ERROR,
+
+    PARKSPACE_ALLOC_REQUEST_CANCELED,
+    PARKSPACE_SEARCH_REQUEST_CANCELED,
+    PARKSPACE_RELEASE_REQUEST_CANCELED,
+
+
+
+
+	//rabbitmq module, 通信模块  新版通信
+ 	RABBITMQ_BASE_ERROR_BASE					= 0x31010000,
+	RABBITMQ_READ_PROTOBUF_ERROR,					//rabbitmq模块,读取PROTO参数错误
+	RABBITMQ_AMQP_NEW_CONNECTION_ERROR,				//rabbitmq模块,新建连接状态错误
+	RABBITMQ_AMQP_TCP_SOCKET_NEW_ERROR,				//rabbitmq模块,新建socket错误
+	RABBITMQ_PROTOBUF_LOSS_ERROR,					//rabbitmq模块,PROTO缺少数据
+	RABBITMQ_AMQP_SOCKET_OPEN_ERROR,				//rabbitmq模块,打开socket错误
+	RABBITMQ_AMQP_LOGIN_ERROR,						//rabbitmq模块,登录服务器错误
+	RABBITMQ_AMQP_CHANNEL_OPEN_ERROR,				//rabbitmq模块,打开通道错误
+	RABBITMQ_AMQP_QUEUE_BIND_ERROR,					//rabbitmq模块,绑定队列错误
+	RABBITMQ_AMQP_NEW_CONSUME_ERROR,				//rabbitmq模块,新建消费者错误
+	RABBITMQ_AMQP_CONSUME_MESSAGE_ERROR,			//rabbitmq模块,接受消息错误
+	RABBITMQ_AMQP_BASIC_PUBLISH_ERROR,				//rabbitmq模块,发送消息错误
+	RABBITMQ_AMQP_BASIC_ACK_ERROR,					//rabbitmq模块,确认消息错误
+
+
+	RABBITMQ_BIND_ERROR,
+	RABBITMQ_CONNECT_ERROR,
+	RABBITMQ_ANALYSIS_TIME_OUT,									//解析超时,
+	RABBITMQ_EXCUTER_IS_BUSY,										//处理器正忙, 请稍等
+
+
+};
+
+//错误等级,用来做故障处理
+enum Error_level
+{
+//    正常,没有错误,默认值0
+    NORMAL                = 0,
+
+
+//    轻微故障,可忽略的故障,NEGLIGIBLE_ERROR
+//    提示作用,不做任何处理,不影响代码的流程,
+//    用作一些不重要的事件,即使出错也不会影响到系统功能,
+//    例如:文件保存错误,等
+    NEGLIGIBLE_ERROR      = 1,
+
+
+//    一般故障,MINOR_ERROR
+//    用作底层功能函数的错误返回,表示该功能函数执行失败,
+//    返回给应用层之后,需要做故障分析和处理,
+//    例如:雷达数据传输失败,应用层就需要进行重新扫描,或者重连,或者重置参数等。
+    MINOR_ERROR           = 2,
+
+
+//    严重故障,MAJOR_ERROR
+//    用作应用层的任务事件的结果,表示该功能模块失败。
+//    通常是底层函数返回一般故障之后,应用层无法处理并解决故障,此时就要进行故障升级,
+//    从一般故障升级为严重故障,然后进行回退流程,回退已经执行的操作,最终回到故障待机状态。
+//    需要外部清除故障,并复位至正常待机状态,才能恢复功能的使用。
+//    例如:雷达扫描任务失败,且无法自动恢复。
+    MAJOR_ERROR           = 3,
+
+
+//    致命故障,CRITICAL_ERROR
+//    系统出现致命错误。导致系统无法正常运行,
+//    此时系统应该紧急停机,执行紧急流程,快速停机。
+//    此时不允许再执行任何函数和任务指令,防止系统故障更加严重。
+//    也不需要做任何错误处理了,快速执行紧急流程。
+//    例如:内存错误,进程挂死,关键设备失控,监控设备报警,等
+    CRITICAL_ERROR        = 4,
+};
+
+
+class Error_manager
+{
+public://外部接口函数
+    //构造函数
+    Error_manager();
+    //拷贝构造
+    Error_manager(const Error_manager & error_manager);
+    //赋值构造
+    Error_manager(Error_code error_code, Error_level error_level = NORMAL,
+                  const char* p_error_description = NULL);
+    //赋值构造
+    Error_manager(Error_code error_code, Error_level error_level , std::string error_aggregate_string);
+    //析构函数
+    ~Error_manager();
+
+    //初始化
+    void error_manager_init();
+    //初始化
+    void error_manager_init(Error_code error_code, Error_level error_level = NORMAL,
+                            const char* p_error_description = NULL);
+    //初始化
+    void error_manager_init(Error_code error_code, Error_level error_level , std::string error_aggregate_string);
+    //重置
+    void error_manager_reset(Error_code error_code, Error_level error_level = NORMAL,
+                             const char* p_error_description = NULL);
+    //重置
+    void error_manager_reset(Error_code error_code, Error_level error_level , std::string error_aggregate_string);
+    //重置
+    void error_manager_reset(const Error_manager & error_manager);
+    //清除所有内容
+    void error_manager_clear_all();
+
+    //重载=
+    Error_manager& operator=(const Error_manager & error_manager);
+    //重载=,支持Error_manager和Error_code的直接转化,会清空错误等级和描述
+    Error_manager& operator=(Error_code error_code);
+    //重载==
+    bool operator==(const Error_manager & error_manager);
+    //重载==,支持Error_manager和Error_code的直接比较
+    bool operator==(Error_code error_code);
+    //重载!=
+    bool operator!=(const Error_manager & error_manager);
+    //重载!=,支持Error_manager和Error_code的直接比较
+    bool operator!=(Error_code error_code);
+	//重载<<,支持cout<<
+	friend std::ostream & operator<<(std::ostream &out, Error_manager &error_manager);
+
+
+    //获取错误码
+    Error_code get_error_code();
+    //获取错误等级
+    Error_level get_error_level();
+    //获取错误描述的指针,(浅拷贝)
+    std::string get_error_description();
+
+    //复制错误描述,(深拷贝)
+    //output:p_error_description     错误描述的字符串指针,不可以为NULL,必须要有实际的内存
+    //output:description_length      错误描述的字符串长度,不可以为0,长度最好足够大,一般256即可。
+    void copy_error_description(const char* p_error_description);
+    //复制错误描述,(深拷贝)
+    //output:error_description_string     错误描述的string
+    void copy_error_description(std::string error_description_string);
+
+    //设置错误码
+    void set_error_code(Error_code error_code);
+    //比较错误等级并升级,取高等级的结果
+    void set_error_level_up(Error_level error_level);
+    //比较错误等级并降级,取低等级的结果
+    void set_error_level_down(Error_level error_level);
+    //错误等级,设定到固定值
+    void set_error_level_location(Error_level error_level);
+    //设置错误描述
+    void set_error_description(const char* p_error_description);
+    //设置错误描述
+    void set_error_description(std::string error_description_string);
+
+    //尾部追加错误描述
+    void add_error_description(const char* p_error_description);
+    //尾部追加错误描述
+    void add_error_description(std::string error_description_string);
+
+    //比较错误是否相同,
+    // 注:只比较错误码和等级
+	bool is_equal_error_manager(const Error_manager & error_manager);
+	//比较并覆盖错误,讲低级错误转为字符串存放于描述中,
+	//如果错误相同,则保留this的,将输入参数转入描述。
+	void compare_and_cover_error(const Error_manager & error_manager);
+	//比较并覆盖错误,讲低级错误转为字符串存放于描述中,
+	//如果错误相同,则保留this的,将输入参数转入描述。
+	void compare_and_cover_error( Error_manager * p_error_manager);
+
+    //output:error_description_string     错误汇总的string
+    void translate_error_to_string(std::string error_aggregate_string);
+    //错误码转字符串的简易版,可支持cout<<
+    //return     错误汇总的string
+    std::string to_string();
+
+
+
+protected:
+    Error_code              m_error_code;               //错误码
+    Error_level             m_error_level;              //错误等级
+    std::string             m_error_description;		// 错误描述
+
+protected://内部功能函数
+public:
+    //释放错误描述的内存,
+    void free_description();
+
+    //重新分配错误描述的内存,并从外部拷贝新的(深拷贝)
+    //input:p_error_description     错误描述的字符串指针,可以为NULL,
+    //input:description_length      错误描述的字符串长度,如果为0,则从p_error_description里面获取有效的长度
+    void reallocate_memory_and_copy_string(const char* p_error_description, int description_length = 0);
+
+    //重新分配错误描述的内存,并从外部拷贝新的(深拷贝)
+    //input:error_aggregate_string     错误描述的string
+    void reallocate_memory_and_copy_string(std::string error_aggregate_string);
+};
+
+
+
+
+#endif //TEST_ERROR_ERROR_CODE_H
+
+

+ 14 - 0
plc调度节点/hulitest.sh

@@ -0,0 +1,14 @@
+#!/bin/bash
+ 
+
+{
+gnome-terminal -x bash -c "cd ./build/&&./terminal 0; exec bash"
+}&
+ 
+{
+gnome-terminal -x bash -c "cd ./build/&&./terminal 1; exec bash"
+}&
+
+{
+gnome-terminal -x bash -c "cd ./build/&&./terminal 2; exec bash"
+}&

+ 220 - 0
plc调度节点/main.cpp

@@ -0,0 +1,220 @@
+//
+//
+// 20210425, hl_dispatch 和 hl_dispatch_B的版本进行同步, 此时调度管理的功能全部完成.后续可能还需要日志记录.
+//
+//test 2022 10 26
+
+
+#include <iostream>
+#include "./error_code/error_code.h"
+//#include "LogFiles.h"
+#include <glog/logging.h>
+#include <string>
+#include <iostream>
+
+#include "./communication/communication_socket_base.h"
+
+#include "./tool/thread_pool.h"
+#include "./system/system_communication.h"
+#include "./system/system_executor.h"
+#include "./rabbitmq/rabbitmq_base.h"
+
+#include "./dispatch/dispatch_manager.h"
+#include "./dispatch/dispatch_communication.h"
+#include "./dispatch/dispatch_coordinates.h"
+#include "./dispatch/database_controller.h"
+
+#include "./tool/common_data.h"
+#include "./tool/time_tool.h"
+
+#include "./rabbitmq/ttt.h"
+
+#include <algorithm>    // std::for_each
+#include <google/protobuf/text_format.h>
+
+//#include <iostream>
+//#include <mysqlx/xdevapi.h>
+//
+//using namespace mysqlx;
+
+GOOGLE_GLOG_DLL_DECL void shut_down_logging(const char* data, int size)
+{
+	time_t tt;
+	time( &tt );
+	tt = tt + 8*3600;  // transform the time zone
+	tm* t= gmtime( &tt );
+	char buf[255]={0};
+	sprintf(buf,"./%d%02d%02d-%02d%02d%02d-dump.txt",
+			t->tm_year + 1900,
+			t->tm_mon + 1,
+			t->tm_mday,
+			t->tm_hour,
+			t->tm_min,
+			t->tm_sec);
+
+	FILE* tp_file=fopen(buf,"w");
+	fprintf(tp_file,data,strlen(data));
+	fclose(tp_file);
+
+}
+
+
+
+
+int main(int argc,char* argv[])
+{
+
+
+
+	Error_manager t_error;
+
+	const char* logPath = "./";
+	google::InitGoogleLogging("LidarMeasurement");
+	google::SetStderrLogging(google::INFO);
+	google::SetLogDestination(0, logPath);
+	google::SetLogFilenameExtension("zxlog");
+	google::InstallFailureSignalHandler();
+	google::InstallFailureWriter(&shut_down_logging);
+	FLAGS_colorlogtostderr = true;        // Set log color
+	FLAGS_logbufsecs = 0;                // Set log output speed(s)
+	FLAGS_max_log_size = 1024;            // Set max log file size(GB)
+	FLAGS_stop_logging_if_full_disk = true;
+
+
+//#define MAIN_TEST 1
+#ifdef MAIN_TEST
+
+	int t_id = 0;
+	if ( argc == 2 )
+	{
+		t_id = stoi(argv[1]);
+	}
+
+//	t_error = Dispatch_coordinates::get_instance_references().dispatch_coordinates_init();
+//	std::cout << " huli test :::: " << " Dispatch_coordinates::get_instance_references().dispatch_coordinates_init() = " << t_error.to_string() << std::endl;
+
+	t_error = Dispatch_communication::get_instance_references().communication_init(t_id);
+	std::cout << " huli test :::: " << " Dispatch_communication::get_instance_references().communication_init() = " << t_error.to_string() << std::endl;
+	std::cout << "Dispatch_communication = " << Dispatch_communication::get_instance_references().get_status() << std::endl;
+
+	t_error = Dispatch_manager::get_instance_references().dispatch_manager_init(t_id);
+	std::cout << " huli test :::: " << " Dispatch_manager::get_instance_references().dispatch_manager_init(0) = " << t_error.to_string() << std::endl;
+	std::cout << "Dispatch_manager = " << Dispatch_manager::get_instance_references().get_dispatch_manager_status() << std::endl;
+
+	System_executor::get_instance_references().system_executor_init(10);
+	std::cout << "System_executor = " << System_executor::get_instance_references().get_system_executor_status() << std::endl;
+	if ( argc == 2 )
+	{
+		System_communication::get_instance_references().communication_init(t_id);
+	}
+	else
+	{
+		System_communication::get_instance_references().communication_init();
+	}
+	System_communication::get_instance_references().set_encapsulate_cycle_time(1000);
+
+//20210922
+	while (1)
+	{
+		std::string test_string;
+		std::cin >> test_string ;
+
+		if ( test_string == "9" )
+		{
+
+			message::Dispatch_request_msg dispatch_request_msg;
+			dispatch_request_msg.mutable_base_info()->set_msg_type(message::Message_type::eDispatch_request_msg);
+			dispatch_request_msg.mutable_base_info()->set_timeout_ms(5000000);
+			dispatch_request_msg.mutable_base_info()->set_sender(message::Communicator::eMain);
+			dispatch_request_msg.mutable_base_info()->set_receiver(message::Communicator::eDispatch_manager);
+			dispatch_request_msg.set_command_key("12345678901234567890123456789012");
+
+			dispatch_request_msg.set_dispatch_motion_direction(message::Dispatch_motion_direction::E_STORE_CAR);
+			dispatch_request_msg.mutable_id_struct()->set_terminal_id(4);
+			dispatch_request_msg.mutable_id_struct()->set_unit_id(2);
+			message::Locate_information t_locate_information;
+			t_locate_information.set_locate_x(-1.901);
+			t_locate_information.set_locate_y(-5.829);
+			t_locate_information.set_locate_angle(2);
+			t_locate_information.set_locate_length(4.78);
+			t_locate_information.set_locate_width(1.88);
+			t_locate_information.set_locate_height(1.65);
+			t_locate_information.set_locate_wheel_base(2.78);
+			t_locate_information.set_locate_wheel_width(1.88);
+			t_locate_information.set_locate_front_theta(0);
+
+			t_locate_information.set_uniformed_car_x(0);
+			t_locate_information.set_uniformed_car_y(0);
+			t_locate_information.set_locate_correct(true);
+			dispatch_request_msg.mutable_locate_information()->CopyFrom(t_locate_information);
+
+			message::Parkspace_info *tp_parkspace_info = dispatch_request_msg.mutable_parkspace_info_ex()->Add();
+			tp_parkspace_info->set_parkingspace_index_id(167);
+			tp_parkspace_info->set_parkingspace_type(message::Parkspace_type::MID_PARKINGSPACE);
+			tp_parkspace_info->set_parkingspace_unit_id(3);
+			tp_parkspace_info->set_parkingspace_label_id(11);
+			tp_parkspace_info->set_parkingspace_room_id(5);
+			tp_parkspace_info->set_parkingspace_direction(message::Direction::eBackward);
+			tp_parkspace_info->set_parkingspace_floor_id(3);
+			tp_parkspace_info->set_parkingspace_width(0);
+			tp_parkspace_info->set_parkingspace_height(0);
+			tp_parkspace_info->set_parkingspace_status(message::Parkspace_status::eParkspace_empty);
+			tp_parkspace_info->set_car_type(message::Car_type::MID_CAR);
+			dispatch_request_msg.set_car_type(message::Car_type::MID_CAR);
+
+			Dispatch_manager::get_instance_references().execute_for_dispatch_request_msg(dispatch_request_msg);
+
+		}
+
+		std::this_thread::sleep_for(std::chrono::seconds(1));
+	}
+	return 0;
+#endif
+
+
+	int t_dispatch_id = 1;
+//	std::cin >> t_dispatch_id ;
+	if ( argc == 2 )
+	{
+		std::cout << " huli test :::: " << " argv[1] = " << argv[1] << std::endl;
+		t_dispatch_id = atoi(argv[1]);
+	}
+	std::cout << "+++++++++++++huli test :::: " << " t_dispatch_id = " << t_dispatch_id << std::endl;
+
+	Database_controller::get_instance_references().database_controller_init();
+	std::cout << "++++++++++++++++++++ Database_controller = " << Database_controller::get_instance_references().get_database_controller_status() << std::endl;
+
+
+	Dispatch_manager::get_instance_references().dispatch_manager_init(t_dispatch_id);
+	std::cout << "++++++++++++++++++++Dispatch_manager = " << Dispatch_manager::get_instance_references().get_dispatch_manager_status() << std::endl;
+
+	Dispatch_communication::get_instance_references().communication_init(t_dispatch_id);
+	std::cout << "+++++++++++++Dispatch_manager = " << Dispatch_manager::get_instance_references().get_dispatch_manager_status() << std::endl;
+
+	System_executor::get_instance_references().system_executor_init(8);
+	std::cout << "++++++++++++++++System_executor = " << System_executor::get_instance_references().get_system_executor_status() << std::endl;
+
+	t_error = System_communication::get_instance_references().communication_init(t_dispatch_id);
+	std::cout << "++++++++++++++++++huli test System_communication:::: " << " t_error = " << t_error << std::endl;
+
+
+	while ( 1 )
+	{
+	    std::this_thread::sleep_for(std::chrono::seconds(1));
+
+	}
+
+
+
+
+	char ch ;
+	std::cin >> ch ;
+
+	System_communication::get_instance_references().rabbitmq_uninit();
+	System_executor::get_instance_references().system_executor_uninit();
+	Dispatch_communication::get_instance_references().communication_uninit();
+	Dispatch_manager::get_instance_references().dispatch_manager_uninit();
+
+
+	return 0;
+}

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 4787 - 0
plc调度节点/message/message.pb.cc


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 2984 - 0
plc调度节点/message/message.pb.h


+ 149 - 0
plc调度节点/message/message.proto

@@ -0,0 +1,149 @@
+syntax = "proto3";
+
+/*测量信息*/
+message measure_info {
+  float cx=1;
+  float cy=2;
+  float theta=3;
+  float length=4;
+  float width=5;
+  float height=6;
+  float wheelbase=7;
+  float front_theta=8;
+  int32 border_statu=9;
+  int32 ground_status=10;                   //0  ok 1,nothing 2,noise  3,border
+}
+
+/*分配的车位信息*/
+message parkspace_info{
+  int32 id=1;
+  int32 unit_id=2;  //单元号
+  int32 floor=3;    //楼层号
+  int32 room_id=4;    //同层编号
+}
+
+enum STATU{
+  eNormal=0;
+  eError=1;
+}
+
+/*
+表单执行状态
+ */
+message table_statu{
+  STATU execute_statu=1;    //执行状态
+  string statu_description=2; //状态描述
+}
+
+/*
+停车表单
+ */
+message park_table{
+  table_statu statu=1;  //表单状态
+  int32 queue_id=2;        //指令排队编号
+
+  string car_number=3;
+  int32 unit_id=4;
+  int32 terminal_id=5;
+  string primary_key=6;
+
+  measure_info entrance_measure_info=7;   //入口测量信息
+
+
+  parkspace_info allocated_space_info=8;       //分配的车位信息
+
+  measure_info actually_measure_info=9;   //实际测量信息或者叫二次测量信息
+
+  parkspace_info actually_space_info=10;      //实际停放的车位
+
+
+}
+
+/*
+取车表单
+ */
+message pick_table{
+  table_statu statu=1;  //表单状态
+  int32 queue_id=2;        //指令排队编号
+
+  string car_number=3;
+  int32 unit_id=4;
+  int32 terminal_id=5;
+  string primary_key=6;
+
+  parkspace_info actually_space_info=7; //实际停放的车位信息
+
+  measure_info actually_measure_info=8; //存车时的实际测量信息(轴距)
+
+  int32 export_id=9;            //分配出口
+  bool  is_leaved=10;         //是否离开
+
+
+}
+
+
+
+/*
+以下是状态消息
+ */
+
+/*
+单片机节点状态
+ */
+message out_mcpu_statu{     //数值+1后
+  int32 door_statu=1;       //外门状态       0无效, 1无效, 2开到位, 3 关到位, 4开关中, 5 故障
+  int32 outside_safety=2;    //是否有车      0无效, 1无车, 2有车
+}
+
+message in_mcpu_statu{      //数值+1后
+  int32 door_statu=1;       //外门状态       0无效, 1无效, 2开到位, 3 关到位, 4开关中, 5 故障
+  int32 back_io=2;          //后超界       0无效, 1后超界, 2正常
+  int32 is_occupy=3;        //是否有车      0无效, 1无车, 2有车
+  int32 heighth=4;          //车高状态      0无效, 1无效, 2小车, 3中车, 4大车, 5故障, 6故障
+}
+/*
+测量节点状态
+ */
+message measure_statu{
+  measure_info info=1;
+}
+
+//搬运器状态枚举
+enum CarrierStatu{
+  eIdle=0;
+  eBusy=1;
+  eFault=2;
+}
+
+//调度入口汽车范围的修正信息
+message dispatch_region_info
+{
+    int32 terminal_id=1;                //入口终端编号, 1~6
+    float turnplate_angle_min=2;        //转盘角度最小值, 负值, 例如 -5度
+    float turnplate_angle_max=3;        //转盘角度最大值, 正值, 例如 +5度
+}
+
+/*
+搬运器状态消息
+ */
+message dispatch_node_statu{
+  CarrierStatu statu=1;
+  int32 idle_stop_floor=2;  //空闲时停留位置
+  park_table  running_pack_info=3;  //正在执行的停车表单
+  pick_table  running_pick_info=4;  //正在执行的取车表单
+
+    int32                                   unit_id = 5;                            //单元号, 1~3
+    int32                                   plc_heartbeat = 6;                      //plc心跳信息
+    int32                                   plc_status_info = 7;                    //plc状态的集合
+                                                                                    		//0 bit, 手动模式
+                                                                                    		//1 bit, 自动模式
+                                                                                    		//2 bit, 自动运行中
+                                                                                    		//3 bit, 复位
+                                                                                    		//4 bit, 1号口可以进车
+                                                                                    		//5 bit, 2号口可以进车
+                                                                                    		//6 bit, 预留
+                                                                                    		//7 bit, 预留
+    repeated dispatch_region_info           dispatch_region_info_vector = 8;        //调度入口汽车范围的修正信息
+
+}
+

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 4207 - 0
plc调度节点/message/message_base.pb.cc


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 3120 - 0
plc调度节点/message/message_base.pb.h


+ 311 - 0
plc调度节点/message/message_base.proto

@@ -0,0 +1,311 @@
+syntax = "proto2";
+package message;
+
+//消息类型定义;每个在网络上传输的消息必须含有这个属性
+enum Message_type
+{
+    eBase_msg=0x00;
+    eCommand_msg=0x01;                      //指令消息
+
+
+    eLocate_status_msg=0x11;                //定位模块状态消息
+    eLocate_request_msg=0x12;               //定位请求消息
+    eLocate_response_msg=0x13;              //定位反馈消息
+
+    eLocate_sift_request_msg = 0x14;            //预测算法请求消息
+    eLocate_sift_response_msg = 0x15;           //预测算法反馈消息
+
+    eDispatch_status_msg=0x21;                //调度模块硬件状态消息
+    eDispatch_request_msg=0x22;              //请求调度消息
+    eDispatch_response_msg=0x23;             //调度结果反馈消息
+
+    eParkspace_allocation_status_msg=0x31;  //车位分配模块状态消息,包括车位信息
+    eParkspace_allocation_request_msg=0x32; //请求分配车位消息
+    eParkspace_allocation_response_msg=0x33;//分配车位结果反馈消息
+    eParkspace_search_request_msg = 0x34;		//查询车位请求消息
+    eParkspace_search_response_msg = 0x35;		//查询车位反馈消息
+    eParkspace_release_request_msg = 0x36;		//释放车位请求消息
+    eParkspace_release_response_msg = 0x37;		//释放车位反馈消息
+    eParkspace_force_update_request_msg = 0x38;	//手动修改车位消息
+    eParkspace_force_update_response_msg = 0x39;//手动修改车位反馈消息
+    eParkspace_confirm_alloc_request_msg = 0x3A;//确认分配车位请求消息
+    eParkspace_confirm_alloc_response_msg = 0x3B;//确认分配车位反馈消息
+    eParkspace_allocation_data_msg = 0x3C;     //车位分配模块车位数据消息
+    eParkspace_allocation_data_response_msg =0x3D;//车位数据反馈消息
+    eParkspace_manual_search_request_msg = 0x3E;	//手动查询车位请求消息
+    eParkspace_manual_search_response_msg = 0x3F;//手动查询车位反馈消息
+
+    eStore_command_request_msg=0x41;        //终端停车请求消息
+    eStore_command_response_msg=0x42;       //停车请求反馈消息
+    ePickup_command_request_msg=0x43;       //取车请求消息
+    ePickup_command_response_msg=0x44;       //取车请求反馈消息
+
+    eTerminal_status_msg = 0x50;	 //终端状态消息
+
+    eStoring_process_statu_msg=0x90;        //停车指令进度条消息
+    ePicking_process_statu_msg=0x91;        //取车指令进度消息
+
+
+    eCentral_controller_statu_msg=0xa0;     //中控系统状态消息
+
+
+    eEntrance_manual_operation_msg=0xb0;            //针对出入口状态操作的手动消息
+    eProcess_manual_operation_msg=0xb1;             //针对流程的手动消息
+
+    eNotify_request_msg=0xc0;               //取车等候区通知请求
+    eNotify_response_msg=0xc1;              //等候区反馈
+    eNotify_status_msg=0xc2;                //等候区通知节点状态
+
+    eUnNormalized_module_statu_msg = 0xd0; //非标节点状态
+
+    eDispatch_plan_request_msg          = 0xe0;     //调度总规划的请求(用于启动整个调度算法)(调度管理->调度算法)
+    eDispatch_plan_response_msg         = 0xe1;     //调度总规划的答复(调度算法->调度管理)
+    eDispatch_control_request_msg       = 0xe2;     //调度控制的任务请求(调度算法->调度管理)
+    eDispatch_control_response_msg      = 0xe3;     //调度控制的任务答复(调度管理->调度算法)
+    eDispatch_manager_status_msg        = 0xea;     //调度管理的设备状态消息(调度底下所有硬件设备状态的汇总)
+    eDispatch_manager_data_msg          = 0xeb;     //调度管理的设备详细的数据信息
+
+
+    eGround_detect_request_msg=0xf0;        //地面雷达测量请求消息
+    eGround_detect_response_msg=0xf1;       //地面雷达测量反馈消息
+    eGround_status_msg=0xf2;                //地面雷达状态消息
+
+}
+
+//通讯单元
+enum Communicator
+{
+    eEmpty=0x0000;
+    eMain=0x0001;    //主流程
+
+    eTerminor=0x0100;
+    //车位表
+    eParkspace=0x0200;
+    //测量单元
+    eMeasurer=0x0300;
+    //测量单元的服务器
+    eMeasurer_sift_server=0x0301;
+    //调度机构
+    eDispatch_manager=0x0400;
+    //调度机构
+    eDispatch_control=0x0401;
+    //...
+  //取车等候区通知节点
+    eNotify=0x0501;
+
+    //地面测量单元
+	eGround_measurer=0x0f00;
+}
+////base message 用于解析未知类型的消息
+message Base_info
+{
+    required Message_type               msg_type=1[default = eBase_msg];
+    optional int32                      timeout_ms=2[default = 0];
+    required Communicator               sender=3[default = eEmpty];                       //发送者
+    required Communicator               receiver=4[default = eEmpty];                     //接收者
+}
+
+// 事件,停车或者取车
+enum Process_type
+{
+    eStoring=1;
+    ePicking=2;
+}
+
+
+message Base_msg
+{
+    required Base_info                  base_info=1;
+}
+
+//错误等级,用来做故障处理
+enum Error_level
+{
+    NORMAL                = 0;      //    正常,没有错误,默认值0
+
+    NEGLIGIBLE_ERROR      = 1;      //    轻微故障;可忽略的故障,NEGLIGIBLE_ERROR
+
+    MINOR_ERROR           = 2;      //    一般故障,MINOR_ERROR
+
+    MAJOR_ERROR           = 3;      //    严重故障,MAJOR_ERROR
+
+    CRITICAL_ERROR        = 4;      //    致命故障,CRITICAL_ERROR
+
+}
+
+message Error_manager
+{
+    required int32                      error_code = 1[default = 0];
+    optional Error_level                error_level = 2[default = NORMAL];
+    optional string                     error_description = 3[default = ""];
+}
+
+//测量结果结构体
+message Locate_information
+{
+    optional float locate_x = 1[default = 0];				//整车的中心点x值; 四轮的中心
+    optional float locate_y = 2[default = 0];				//整车的中心点y值; 四轮的中心
+    optional float locate_angle = 3[default = 0];			//整车的旋转角; 四轮的旋转角
+    optional float locate_length = 4[default = 0];		    //整车的长度; 用于规避碰撞
+    optional float locate_width = 5[default = 0];			//整车的宽度; 用于规避碰撞
+    optional float locate_height = 6[default = 0];		    //整车的高度; 用于规避碰撞
+    optional float locate_wheel_base = 7[default = 0];	    //整车的轮距; 前后轮的距离; 用于机器人或agv的抓车
+    optional float locate_wheel_width = 8[default = 0];	    //整车的轮距; 左右轮的距离; 用于机器人或agv的抓车
+    optional bool locate_correct = 9[default = false];		    //整车的校准标记位
+
+    optional float locate_front_theta = 10[default = 0];	    //整车的前轮的旋转角
+    
+    optional float uniformed_car_x = 11;        //转角复位后,车辆中心点x
+    optional float uniformed_car_y = 12;        //转角复位后,车辆中心点y
+}
+
+//车辆基本信息
+message Car_info
+{
+    optional float                      car_length=1[default = 0];           //车长
+    optional float                      car_width=2[default = 0];            //车宽
+    optional float                      car_height=3[default = 0];           //车高
+    optional string                     license=4[default = ""];             //车辆凭证号(车牌号+唯一码)
+    optional string                     car_numberPlate = 5[default = ""];   //车牌号
+    optional float                      car_wheel_base = 6[default = 0];	 //整车的轮距; 前后轮的距离; 用于机器人或agv的抓车
+    optional float                      car_wheel_width = 7[default = 0];	 //整车的轮距; 左右轮的距离; 用于机器人或agv的抓车
+}
+
+//车位状态枚举
+enum Parkspace_status
+{
+    eParkspace_status_unknow    = 0;
+    eParkspace_empty            = 1;         //空闲,可分配
+    eParkspace_occupied         = 2;         //被占用,不可分配
+    eParkspace_reserved         = 3;         //被预约,预约车辆可分配
+    eParkspace_locked           = 4;         //临时锁定,不可分配
+    eParkspace_error            = 5;         //车位机械结构或硬件故障
+}
+
+//车位朝向, 0:未知, 1:小号朝前朝南, 也指入口, 2:大号朝后朝北, 也指出口,
+enum Direction
+{
+    eDirection_unknow = 0;
+    eForward = 1;                   //小号朝前朝南, 也指入口
+    eBackward = 2;                  //大号朝后朝北, 也指出口
+}
+
+//车位分配路线(根据中跑车的路线来定)
+enum Parkspace_path
+{
+	UNKNOW_PATH = 0;
+    OPTIMAL_PATH = 1;
+    LEFT_PATH = 2;
+    RIGHT_PATH = 3;
+    TEMPORARY_CACHE_PATH = 4;
+}
+
+//车位类型
+enum Parkspace_type
+{
+    UNKNOW_PARKSPACE_TYPE = 0;
+    MIN_PARKINGSPACE = 1;//小车位
+    MID_PARKINGSPACE = 2;//中车位
+    BIG_PARKINGSPACE = 3;//大车位
+}
+
+//汽车类型
+enum Car_type
+{
+    UNKNOW_CAR_TYPE = 0;
+    MIN_CAR = 1;//小车
+    MID_CAR = 2;//中车
+    BIG_CAR = 3;//大车
+}
+
+//单个车位基本信息与状态信息,车位信息以及车位上的车辆信息
+message Parkspace_info
+{
+    optional int32              parkingspace_index_id = 1;            //车位ID
+    optional Parkspace_type     parkingspace_type = 2;                //车位类型
+    optional int32              parkingspace_unit_id = 3;            //车位单元号
+    optional int32              parkingspace_label_id = 4;            //车位单元内部ID
+    optional int32              parkingspace_room_id = 5;             //同层编号
+    optional Direction          parkingspace_direction = 6;           //前后
+    optional int32              parkingspace_floor_id = 7;            //楼层
+    optional float              parkingspace_width = 8;               //车位宽
+    optional float              parkingspace_height = 9;              //车位高
+    optional Parkspace_status   parkingspace_status = 10;              //车位当前状态
+    optional Car_info           car_info = 11;                        //车辆信息
+    optional string             entry_time = 12;                      //入场时间
+    optional string             leave_time = 13;                      //离场时间
+
+
+    optional Parkspace_path     parkspace_path = 14;            // 车位分配路线
+    optional float              path_estimate_time = 15;        //车位分配路线 time(s)
+    optional Parkspace_status   parkspace_status_target = 16;     //车位目标状态
+
+    optional Car_type           car_type = 17;                        //车辆类型
+
+
+}
+
+/*
+*流程中的步骤类型, 例如:停车流程包含5个步骤 , 分配车位-测量-检验结果-搬运-更新车位表
+*/
+enum Step_type
+{
+    eAlloc_step=0;
+    eMeasure_step=1;
+    eCompare_step=2;
+    eDispatch_step=3;
+    eConfirm_step=4;
+
+    eSearch_step=5;        //查询数据库
+    eWait_step=6;             //等待车辆离开
+    eRelease_step=7;          //释放车位
+
+    eComplete=8;              //完成
+
+    eBackConfirm_step=9;
+    eBack_compare_step=10;
+    eBackMeasure_step=11;
+    eBackAlloc_step=12;
+
+    eBackWait_step=13;
+    eBackDispatch_step=14;
+    eBackSearch_step=15;
+
+    eBackComplete=16;
+}
+//步骤状态,每个步骤有四中可能状态 ,等待中-执行中-完成或者错误  四个状态
+enum Step_statu
+{
+    eWaiting=0;               //完成/空闲
+    eWorking=1;
+    eError=2;
+    eFinished=3;
+}
+
+//调度设备的类型
+enum Dispatch_device_type
+{
+    ROBOT_1                                 = 101;      //一号出口的专用机器手(只能负责1号出口的取车)(目前没有安装,暂时不考虑)
+    ROBOT_2                                 = 102;      //中间的大型机器手   (可以负责1~6号出入口的停车和取车)
+
+    CARRIER_1                               = 200;      //左侧0号电梯井的搬运器(升降电梯 中跑车 小跑车 三合一为搬运器)
+    CARRIER_2                               = 207;      //右侧7号电梯井的搬运器(升降电梯 中跑车 小跑车 三合一为搬运器)
+    CARRIER_3                               = 203;      //中间3楼的搬运器(中跑车 小跑车 二合一为搬运器)(没有电梯, 只能在3楼活动)
+
+    PASSAGEWAY_0                            = 300;      //0号出口(在左侧电梯井, 只能取车)(暂时不存在)
+    PASSAGEWAY_1                            = 301;      //1号出入口
+    PASSAGEWAY_2                            = 302;      //2号出入口
+    PASSAGEWAY_3                            = 303;      //3号出入口
+    PASSAGEWAY_4                            = 304;      //4号出入口
+    PASSAGEWAY_5                            = 305;      //5号出入口
+    PASSAGEWAY_6                            = 306;      //6号出入口
+    PASSAGEWAY_7                            = 307;      //7号出口(在右侧电梯井, 只能取车)
+}
+
+//id结构体
+message Id_struct
+{
+    optional int32              terminal_id = 1;            //终端ID
+    optional int32              unit_id =  2;               //单元号
+}
+

+ 28 - 0
plc调度节点/proto.sh

@@ -0,0 +1,28 @@
+
+protoc -I=./communication communication.proto --cpp_out=./communication
+protoc -I=./snap7_communication snap7_communication.proto --cpp_out=./snap7_communication
+protoc -I=./dispatch dispatch_parameter.proto --cpp_out=./dispatch
+protoc -I=./rabbitmq rabbitmq.proto --cpp_out=./rabbitmq
+protoc -I=./dispatch database_communication_configuration.proto --cpp_out=./dispatch
+
+
+protoc -I=./message message_base.proto --cpp_out=./message
+#protoc -I=./message measure_message.proto --cpp_out=./message
+#protoc -I=./message dispatch_message.proto --cpp_out=./message
+#protoc -I=./message dispatch_control.proto --cpp_out=./message
+#protoc -I=./message parkspace_allocation_message.proto --cpp_out=./message
+
+#protoc -I=./message singlechip_msg.proto --cpp_out=./message
+#protoc -I=./message notify_message.proto --cpp_out=./message
+
+protoc -I=./message message.proto --cpp_out=./message
+
+
+#protoc -I=./message central_control_message.proto --cpp_out=./message
+#protoc -I=./message log_process.proto --cpp_out=./message
+#protoc -I=./message process_message.proto --cpp_out=./message
+#protoc -I=./message terminal_message.proto --cpp_out=./message
+#protoc -I=./message UnNormalized_module_message.proto --cpp_out=./message
+
+
+

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 1956 - 0
plc调度节点/rabbitmq/rabbitmq.pb.cc


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 1620 - 0
plc调度节点/rabbitmq/rabbitmq.pb.h


+ 67 - 0
plc调度节点/rabbitmq/rabbitmq.proto

@@ -0,0 +1,67 @@
+syntax = "proto2";
+package Rabbitmq_proto;
+
+//Rabbitmq 配置的通道,队列和消费者,
+//注:目前规定
+//接受请求消息:同一子节点所有的请求消息写同一个channel通道编号,queue_durable = 1, queue_auto_delete = 0, consume_no_ack = 0,
+//接受状态消息:同一子节点所有的状态消息写同一个channel通道编号,queue_durable = 0, queue_auto_delete = 1, consume_no_ack = 1,
+message Rabbitmq_channel_queue_consume
+{
+    optional int32 channel = 1;                             //连接通道,必写, 可以相同, 不同的消息队列可以共用同一个连接通道,
+                                                            //配合 amqp_basic_qos 和 amqp_basic_ack , 来阻塞这个通道的接受消息
+                                                            //请求消息和状态消息必须分别写不同的通道,例如所有的请求都可以写12, 所有的状态都可以写34
+    optional string exchange_name = 2;                      //交换机名称,必写, 可以相同, 不同的消息队列可以共用同一个交换机,
+                                                            //配合 routingkey 和 bindingkey , 来分配消息到合适的队列
+
+    //发送队列专属
+    optional string routing_key = 3;                        //发送端的路由键, 交换机分配消息的判断条件
+    optional int32 timeout_ms = 4;                          //发送超时时间, 单位ms, 服务器会自动删除超时的消息, 如果写0,那么就没有超时删除
+
+    //接受队列专属
+    optional string binding_key = 5;                        //接受端的绑定键, 交换机分配消息的判断条件
+    optional string queue_name = 6;                         //队列名称,必写, 不能相同
+    optional int32 queue_passive = 7[default = 0];          //是否被动,默认0
+    optional int32 queue_durable = 8;                       //是否持久,必写, 节点代码可以创建临时队列(所有权归节点), 服务器手动创建永久队列(所有权归服务器)
+                                              		        //		1表示永久队列,当节点死掉,队列在服务器保留,仍然可以接受数据,节点上线后,可以接受掉线期间的所有数据
+                                              		        //		0表示临时队列,当节点死掉,队列消失,不再接受数据,直到下次恢复正常
+    optional int32 queue_exclusive = 9[default = 0];        //是否独立,默认0
+    optional int32 queue_auto_delete = 10[default = 0];      //是否自动删除, 固定写0,
+                                                            //1表示消息被消费者接受后,就自动删除消息, 当接收端断连后,队列也会删除,
+                                                            //0表示消息被消费者接受后,不会自动删除消息, 需要手动ack才会删除消息, 队列不会删除
+                                                            //一般情况下设为0,然后让接受者手动删除.
+     optional int32 queue_meassage_ttl = 11[default = 0];   //队列配置的扩展参数, x-message-ttl 队列接受消息 的超时时间 (单位毫秒)
+                                                            //默认写0, 不配置超时, 一般在状态消息的临时队列写入1000ms
+
+
+    optional string consume_name = 12;                       //消费者名称,必写, 不能相同
+    optional int32 consume_no_local = 13[default = 0];      //是否非本地, 默认0,表示本地
+    optional int32 consume_no_ack = 14[default = 0];        //是否确认应答,默认0,表示接收后需要应答
+                                                            //请求消息必须写0, 必须应答之后才能接受下一条
+                                                            //状态消息必须写1, 可以无限循环接受,收到的瞬间,服务器就会删除这一条消息
+    optional int32 consume_exclusive = 15;                  //是否独立,默认0
+
+}
+
+
+
+//Rabbitmq 配置参数
+message Rabbitmq_parameter
+{
+    optional string ip = 1;             //服务器ip地址, 不带端口
+    optional int32 port = 2;            //端口,默认5672
+    optional string user = 3;           //用户名, 默认guest
+    optional string password = 4;       //密码, 默认guest
+
+    repeated Rabbitmq_channel_queue_consume rabbitmq_reciever_vector= 5;                //Rabbitmq 接受的通道,队列和消费者, 多个
+    repeated Rabbitmq_channel_queue_consume rabbitmq_sender_request_vector= 6;         //Rabbitmq 发送请求的通道
+    repeated Rabbitmq_channel_queue_consume rabbitmq_sender_status_vector= 7;          //Rabbitmq 发送状态的通道
+    //注:rabbitmq的接受是以队列为目标的, 可以同时接受多个队列的消息.
+    //注:rabbitmq的发送是以交换机为目标的,我们发送到交换机后,由交换机按照规则,去分配到下面的队列里面
+
+}
+
+//Rabbitmq 配置参数 总配置
+message Rabbitmq_parameter_all
+{
+    optional Rabbitmq_parameter        rabbitmq_parameters=1;
+}

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 1074 - 0
plc调度节点/rabbitmq/rabbitmq_base.cpp


+ 190 - 0
plc调度节点/rabbitmq/rabbitmq_base.h

@@ -0,0 +1,190 @@
+
+/*
+ * rabbitmq_base 通信模块的基类,
+ * 用户从这个基类继承, 初始化之后, 便可以自动进行通信
+ * 重载解析消息和封装消息,
+
+ nanosmg 必须实时接受消息, 如果不收可能就丢包, 所以本地开启了接受线程和解析线程.
+ 	接受线程实时接受,然后缓存到本地list, 然后解析线程再慢慢处理.
+ rabbitmq 的服务器可以缓存消息, 如果子节点不接受, 数据仍然留在服务器上, 在需要的时候再去接受,不会丢包.
+ 	因此删除了接受线程和缓存list, 直接使用解析线程,一边接受一边处理,处理完后再接受下一条.
+
+ * */
+
+#ifndef __RIBBITMQ_BASE__HH__
+#define __RIBBITMQ_BASE__HH__
+
+#include <mutex>
+#include <thread>
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <map>
+#include "../tool/proto_tool.h"
+
+//#ifdef _WIN32
+//#ifndef WIN32_LEAN_AND_MEAN
+//#define WIN32_LEAN_AND_MEAN
+//#endif
+//#include <Winsock2.h>
+//#else
+//#include <sys/time.h>
+//#endif
+
+#include <rabbitmq-c/amqp.h>
+#include <rabbitmq-c/tcp_socket.h>
+#include <assert.h>
+
+#include <glog/logging.h>
+#include "../error_code/error_code.h"
+#include "../tool/binary_buf.h"
+#include "../tool/thread_safe_list.h"
+#include "../tool/thread_condition.h"
+
+#include "../message/message_base.pb.h"
+#include "../rabbitmq/rabbitmq.pb.h"
+#include "../rabbitmq/rabbitmq_message.h"
+
+//rabbitmq初始化配置参数的默认路径
+#define RABBITMQ_PARAMETER_PATH "../setting/rabbitmq.prototxt"
+//amqp_basic_qos设置通道每次只能接受PREFETCH_COUNT条消息, 默认每次只能同时接受1条消息
+#define PREFETCH_COUNT 1
+
+class Rabbitmq_base
+{
+	//通信状态
+	enum Rabbitmq_status
+	{
+		RABBITMQ_STATUS_UNKNOW = 0,            	//通信状态 未知
+		RABBITMQ_STATUS_READY = 1,            	//通信状态 正常
+		RABBITMQ_STATUS_DISCONNECT = 11,            	//通信状态 断连(可能会在断连和重连之间反复跳动)
+		RABBITMQ_STATUS_RECONNNECT = 12,            	//通信状态 重连(可能会在断连和重连之间反复跳动)
+
+
+		RABBITMQ_STATUS_FAULT = 100,         	//通信状态 错误
+	};
+
+public:
+	Rabbitmq_base();
+	Rabbitmq_base(const Rabbitmq_base &other) = delete;
+	Rabbitmq_base &operator=(const Rabbitmq_base &other) = delete;
+	~Rabbitmq_base();
+
+public://API functions
+	//初始化 通信 模块。如下三选一
+	Error_manager rabbitmq_init();
+	//初始化 通信 模块。从文件读取
+	Error_manager rabbitmq_init_from_protobuf(std::string prototxt_path);
+	//初始化 通信 模块。从protobuf读取
+	Error_manager rabbitmq_init_from_protobuf(Rabbitmq_proto::Rabbitmq_parameter_all &rabbitmq_parameter_all);
+
+	//反初始化 通信 模块。
+	Error_manager rabbitmq_uninit();
+	//重连, 快速uninit, init
+	Error_manager rabbitmq_reconnnect();
+
+	//手动封装消息, 如下四选一
+	//手动封装消息,需要手动写入参数channel,exchange_name,routing_key
+	Error_manager encapsulate_msg(std::string message, int channel, std::string exchange_name, std::string routing_key, int timeout_ms);
+	//手动封装消息,需要手动写入参数channel,exchange_name,routing_key
+	Error_manager encapsulate_msg(Rabbitmq_message* p_msg);
+	//手动封装任务消息(请求和答复), 系统会使用rabbitmq.proto的配置参数,
+	Error_manager encapsulate_task_msg(std::string message, int vector_index=0);
+	//手动封装状态消息, 系统会使用rabbitmq.proto的配置参数,
+	Error_manager encapsulate_status_msg(std::string message, int vector_index=0);
+
+	//ack_msg 处理完消息后, 手动确认消息, 通知服务器队列删除消息.
+	//执行者在execute_msg里面可以调用这个函数, 或者回调也行.
+	Error_manager ack_msg(Rabbitmq_message* p_msg);
+
+	//设置 自动封装状态的时间周期, 可选(默认1000ms)
+	void set_encapsulate_status_cycle_time(unsigned int encapsulate_status_cycle_time);
+
+	//设置回调函数check_msg_callback
+	void set_check_msg_callback(Error_manager (*callback)(Rabbitmq_message* p_msg));
+	//设置回调函数check_executer_callback
+	void set_check_executer_callback(Error_manager (*callback)(Rabbitmq_message* p_msg));
+	//设置回调函数execute_msg_callback
+	void set_execute_msg_callback(Error_manager (*callback)(Rabbitmq_message* p_msg));
+	//设置回调函数encapsulate_status_callback
+	void set_encapsulate_status_callback(Error_manager (*callback)());
+
+protected:
+	//创建通道队列消费者, (交换机和永久队列不在代码里创建,请在服务器上手动创建)
+	Error_manager rabbitmq_new_channel_queue_consume(Rabbitmq_proto::Rabbitmq_parameter_all &rabbitmq_parameter_all);
+	//启动通信, 开启线程, run thread
+	Error_manager rabbitmq_run();
+
+
+
+	//mp_receive_analysis_thread 接受解析 执行函数,
+	void receive_analysis_thread();
+	//检查消息是否有效, 主要检查消息类型和接受者, 判断这条消息是不是给我的., 需要子类重载
+	virtual Error_manager check_msg(Rabbitmq_message* p_msg);
+	//检查执行者的状态, 判断能否处理这条消息, 需要子类重载
+	virtual Error_manager check_executer(Rabbitmq_message* p_msg);
+	//处理消息, 需要子类重载
+	virtual Error_manager execute_msg(Rabbitmq_message* p_msg);
+
+	//mp_send_thread 发送线程执行函数,
+	void send_thread();
+
+	//mp_encapsulate_stauts_thread 自动封装线程执行函数,
+	void encapsulate_status_thread();
+	//定时封装发送消息, 一般为心跳和状态信息, 需要子类重载
+	virtual Error_manager auto_encapsulate_status();
+
+protected:
+	//把rabbitmq的错误信息转化为string, amqp_status就是enum amqp_status_enum_, amqp_error_string2()函数可以把他翻译为string
+	std::string amqp_error_to_string(int amqp_status);
+	//把rabbitmq的错误信息转化为string, amqp_status就是enum amqp_status_enum_, amqp_error_string2()函数可以把他翻译为string
+	std::string amqp_error_to_string(int amqp_status, std::string amqp_fun_name);
+	//把rabbitmq的错误信息转化为string, amqp_rpc_reply_t就是amqp函数运行的结果
+	std::string amqp_error_to_string(amqp_rpc_reply_t amqp_rpc_reply);
+	//把rabbitmq的错误信息转化为string, amqp_rpc_reply_t就是amqp函数运行的结果
+	std::string amqp_error_to_string(amqp_rpc_reply_t amqp_rpc_reply, std::string amqp_fun_name);
+
+protected://member variable
+	Rabbitmq_status					m_rabbitmq_status;		//通信状态
+
+	//rabbitmq网络通信 连接配置信息
+	Rabbitmq_proto::Rabbitmq_parameter_all		m_rabbitmq_parameter_all;
+	amqp_connection_state_t_ *  	mp_connect;		// 连接参数的结构体, 内存系统自动分配,自动释放
+	amqp_socket_t * 				mp_socket ;		// 网口通信socket, 内存系统自动分配,自动释放
+	std::string						m_ip;			//服务器ip地址, 不带端口
+	int 							m_port;			//端口,默认5672
+	std::string						m_user;			//用户名, 默认guest
+	std::string						m_password;		//密码, 默认guest
+	std::mutex 						m_mutex;		// socket的锁, 发送和接受的通信锁
+	std::map<int, bool>				m_channel_map;	// 通道的缓存,防止重复开启
+
+	//接受模块,
+	//rabbitmq 的服务器可以缓存消息, 如果子节点不接受, 数据仍然留在服务器上, 在需要的时候再去接受,不会丢包.
+	//因此删除了接受线程和缓存list, 直接使用解析线程,一边接受一边处理,处理完后再接受下一条.
+	std::thread*							mp_receive_analysis_thread;    			//接受解析的线程指针
+	Thread_condition						m_receive_analysis_condition;			//接受解析的条件变量
+
+	//发送模块,
+	Thread_safe_list<Rabbitmq_message*>		m_send_list;				//发送的list容器
+	std::thread*							mp_send_thread;    			//发送的线程指针
+	Thread_condition						m_send_condition;			//发送的条件变量
+	//自动发送状态的
+	std::thread*							mp_encapsulate_status_thread;    		//自动封装状态的线程指针
+	Thread_condition						m_encapsulate_status_condition;			//自动封装状态的条件变量
+	unsigned int 							m_encapsulate_status_cycle_time;		//自动封装状态的时间周期
+
+	//回调函数,
+	// //可以选择设置回调函数,或者子类继承重载,二选一.
+	Error_manager (*check_msg_callback)(Rabbitmq_message* p_msg);
+	Error_manager (*check_executer_callback)(Rabbitmq_message* p_msg);
+	Error_manager (*execute_msg_callback)(Rabbitmq_message* p_msg);
+	Error_manager (*encapsulate_status_callback)();
+};
+
+
+
+
+#endif //__RIBBITMQ_BASE__HH__

+ 109 - 0
plc调度节点/rabbitmq/rabbitmq_message.cpp

@@ -0,0 +1,109 @@
+
+
+
+
+#include "rabbitmq_message.h"
+
+
+Rabbitmq_message::Rabbitmq_message()
+{
+	m_message_type = message::Message_type::eBase_msg;
+	m_receive_time = std::chrono::system_clock::now();
+	m_timeout_ms = std::chrono::milliseconds(0);		//超时默认0秒
+	m_sender = message::Communicator::eEmpty;
+	m_receiver = message::Communicator::eEmpty;
+//	m_message_buf = "";
+}
+
+Rabbitmq_message::Rabbitmq_message(const message::Base_info& base_info, std::string receive_string, int channel, int delivery_tag, std::string exchange_name, std::string routing_key)
+{
+	m_message_type = (message::Message_type)(base_info.msg_type());
+
+	m_receive_time = std::chrono::system_clock::now();
+	m_timeout_ms = std::chrono::milliseconds(base_info.timeout_ms());
+	m_sender = (message::Communicator)(base_info.sender());
+	m_receiver = (message::Communicator)(base_info.receiver());
+	m_message_buf = receive_string;
+
+	m_channel = channel;
+	m_delivery_tag = delivery_tag;
+	m_exchange_name = exchange_name;
+	m_routing_key = routing_key;
+}
+
+Rabbitmq_message::Rabbitmq_message(std::string receive_string, int channel, std::string exchange_name, std::string routing_key, int timeout_ms=0)
+{
+	m_timeout_ms = std::chrono::milliseconds(timeout_ms);
+	m_message_buf = receive_string;
+	m_channel = channel;
+	m_exchange_name = exchange_name;
+	m_routing_key = routing_key;
+}
+
+
+
+Rabbitmq_message::~Rabbitmq_message()
+{
+
+}
+
+bool Rabbitmq_message::is_over_time()
+{
+	if ( std::chrono::system_clock::now() - m_receive_time > m_timeout_ms)
+	{
+		return true;
+	}
+	else
+	{
+		return false;
+	}
+}
+
+
+void Rabbitmq_message::reset(const message::Base_info& base_info, std::string receive_string, int channel, int delivery_tag, std::string exchange_name, std::string routing_key)
+{
+	m_message_type = (message::Message_type)(base_info.msg_type());
+
+	m_receive_time = std::chrono::system_clock::now();
+	m_timeout_ms = std::chrono::milliseconds(base_info.timeout_ms());
+	m_sender = (message::Communicator)(base_info.sender());
+	m_receiver = (message::Communicator)(base_info.receiver());
+	m_message_buf = receive_string;
+	m_channel = channel;
+	m_delivery_tag = delivery_tag;
+	m_exchange_name = exchange_name;
+	m_routing_key = routing_key;
+}
+void Rabbitmq_message::reset(std::string receive_string, int channel, std::string exchange_name, std::string routing_key, int timeout_ms = 0)
+{
+	m_timeout_ms = std::chrono::milliseconds(timeout_ms);
+	m_message_buf = receive_string;
+	m_channel = channel;
+	m_exchange_name = exchange_name;
+	m_routing_key = routing_key;
+}
+
+message::Message_type Rabbitmq_message::get_message_type()
+{
+	return m_message_type;
+}
+message::Communicator Rabbitmq_message::get_sender()
+{
+	return m_sender;
+}
+message::Communicator Rabbitmq_message::get_receiver()
+{
+	return m_receiver;
+}
+std::string Rabbitmq_message::get_message_buf()
+{
+	return m_message_buf;
+}
+
+std::chrono::system_clock::time_point Rabbitmq_message::get_receive_time()
+{
+	return m_receive_time;
+}
+
+
+

+ 62 - 0
plc调度节点/rabbitmq/rabbitmq_message.h

@@ -0,0 +1,62 @@
+//
+// Created by huli on 2020/6/29.
+//
+
+#ifndef __RABBITMQ_MESSAGE_H
+#define __RABBITMQ_MESSAGE_H
+
+#include "../error_code/error_code.h"
+
+#include <time.h>
+#include <sys/time.h>
+#include <chrono>
+//#include <iosfwd>
+
+#include <string>
+#include "../message/message_base.pb.h"
+
+
+class Rabbitmq_message
+{
+public:
+	Rabbitmq_message();
+	Rabbitmq_message(const message::Base_info& base_info, std::string receive_string, int channel, int delivery_tag, std::string exchange_name, std::string routing_key);
+	Rabbitmq_message(std::string receive_string, int channel, std::string exchange_name, std::string routing_key, int timeout_ms);
+	Rabbitmq_message(const Rabbitmq_message& other)= default;
+	Rabbitmq_message& operator =(const Rabbitmq_message& other)= default;
+	~Rabbitmq_message();
+public://API functions
+	bool is_over_time();
+public://get or set member variable
+	void reset(const message::Base_info& base_info, std::string receive_string, int channel, int delivery_tag, std::string exchange_name, std::string routing_key);
+	void reset(std::string receive_string, int channel, std::string exchange_name, std::string routing_key, int timeout_ms);
+
+	message::Message_type get_message_type();
+	message::Communicator get_sender();
+	message::Communicator get_receiver();
+	std::string get_message_buf();
+	std::chrono::system_clock::time_point get_receive_time();
+
+public://member variable
+	message::Message_type								m_message_type;				//消息类型
+	std::chrono::system_clock::time_point				m_receive_time;				//接收消息的时间点
+	std::chrono::milliseconds							m_timeout_ms;				//超时时间, 整个软件都统一为毫秒
+	message::Communicator								m_sender;					//发送者
+	message::Communicator								m_receiver;					//接受者
+
+	std::string											m_message_buf;				//消息数据
+
+	//rabbitmq 接受特有, 保存channel和delivery_tag, 用来ack
+	//rabbitmq 通用, 填写m_channel m_exchange_name m_routing_key 用来区别消息
+	int													m_channel;					//接受消息来源的通道
+	int													m_delivery_tag;				//接受消息的传递编号
+	std::string											m_exchange_name;			//交换机名称
+	std::string											m_routing_key;				//key,识别码
+
+
+private:
+
+};
+
+
+#endif //__RABBITMQ_MESSAGE_H

+ 303 - 0
plc调度节点/rabbitmq/ttt.cpp

@@ -0,0 +1,303 @@
+#include "ttt.h"
+#include <unistd.h>
+
+
+CRabbitmqClient::CRabbitmqClient()
+: m_strHostname("")
+, m_iPort(0)
+, m_strUser("")
+, m_strPasswd("")
+, m_iChannel(1) //默认用1号通道,通道无所谓
+, m_pSock(NULL)
+, m_pConn(NULL) {
+
+}
+
+CRabbitmqClient::~CRabbitmqClient() {
+	if (NULL != m_pConn) {
+		Disconnect();
+		m_pConn = NULL;
+	}
+}
+
+int CRabbitmqClient::Connect(const string &strHostname, int iPort, const string &strUser, const string &strPasswd) {
+	m_strHostname = strHostname;
+	m_iPort = iPort;
+	m_strUser = strUser;
+	m_strPasswd = strPasswd;
+
+	m_pConn = amqp_new_connection();
+	if (NULL == m_pConn) {
+		fprintf(stderr, "amqp new connection failed\n");
+		return -1;
+	}
+
+	m_pSock =  amqp_tcp_socket_new(m_pConn);
+	if (NULL == m_pSock) {
+		fprintf(stderr, "amqp tcp new socket failed\n");
+		return -2;
+	}
+
+	int status = amqp_socket_open(m_pSock, m_strHostname.c_str(), m_iPort);
+	if (status<0) {
+		fprintf(stderr, "amqp socket open failed\n");
+		return -3;
+	}
+
+	// amqp_login(amqp_connection_state_t state,char const *vhost, int channel_max, int frame_max, int heartbeat, amqp_sasl_method_enum sasl_method, ..)
+	if (0 != ErrorMsg(amqp_login(m_pConn, "/", 0, 131072, 0, AMQP_SASL_METHOD_PLAIN, m_strUser.c_str(), m_strPasswd.c_str()), "Logging in")) {
+		return -4;
+	}
+
+	return 0;
+}
+
+int CRabbitmqClient::Disconnect() {
+	if (NULL != m_pConn) {
+		if (0 != ErrorMsg(amqp_connection_close(m_pConn, AMQP_REPLY_SUCCESS), "Closing connection"))
+			return -1;
+
+		if (amqp_destroy_connection(m_pConn) < 0)
+			return -2;
+
+		m_pConn = NULL;
+	}
+
+	return 0;
+}
+
+int CRabbitmqClient::ExchangeDeclare(const string &strExchange, const string &strType) {
+	amqp_channel_open(m_pConn, m_iChannel);
+
+	amqp_bytes_t _exchange = amqp_cstring_bytes(strExchange.c_str());
+	amqp_bytes_t _type = amqp_cstring_bytes(strType.c_str());
+	int _passive= 0;
+	int _durable= 0;      // 交换机是否持久化
+	amqp_exchange_declare(m_pConn, m_iChannel, _exchange, _type, _passive, _durable, 0, 0, amqp_empty_table);
+	if (0 != ErrorMsg(amqp_get_rpc_reply(m_pConn), "exchange_declare")) {
+		amqp_channel_close(m_pConn, m_iChannel, AMQP_REPLY_SUCCESS);
+		return -1;
+	}
+
+	amqp_channel_close(m_pConn, m_iChannel, AMQP_REPLY_SUCCESS);
+	return 0;
+}
+
+int CRabbitmqClient::QueueDeclare(const string &strQueueName) {
+	if(NULL == m_pConn) {
+		fprintf(stderr, "QueueDeclare m_pConn is null\n");
+		return -1;
+	}
+
+	amqp_channel_open(m_pConn, m_iChannel);
+	amqp_bytes_t _queue = amqp_cstring_bytes(strQueueName.c_str());
+	int32_t _passive = 0;
+	int32_t _durable = 0;
+	int32_t _exclusive = 0;
+	int32_t _auto_delete = 1;
+	amqp_queue_declare(m_pConn, m_iChannel, _queue, _passive, _durable, _exclusive, _auto_delete, amqp_empty_table);
+	if (0 != ErrorMsg(amqp_get_rpc_reply(m_pConn), "queue_declare")) {
+		amqp_channel_close(m_pConn, m_iChannel, AMQP_REPLY_SUCCESS);
+		return -1;
+	}
+
+	amqp_channel_close(m_pConn, m_iChannel, AMQP_REPLY_SUCCESS);
+	return 0;
+}
+
+int CRabbitmqClient::QueueBind(const string &strQueueName, const string &strExchange, const string &strBindKey) {
+	if(NULL == m_pConn) {
+		fprintf(stderr, "QueueBind m_pConn is null\n");
+		return -1;
+	}
+
+	amqp_channel_open(m_pConn, m_iChannel);
+	amqp_bytes_t _queue = amqp_cstring_bytes(strQueueName.c_str());
+	amqp_bytes_t _exchange = amqp_cstring_bytes(strExchange.c_str());
+	amqp_bytes_t _routkey  = amqp_cstring_bytes(strBindKey.c_str());
+	amqp_queue_bind(m_pConn, m_iChannel, _queue, _exchange, _routkey, amqp_empty_table);
+	if(0 != ErrorMsg(amqp_get_rpc_reply(m_pConn), "queue_bind")) {
+		amqp_channel_close(m_pConn, m_iChannel, AMQP_REPLY_SUCCESS);
+		return -1;
+	}
+
+	amqp_channel_close(m_pConn, m_iChannel, AMQP_REPLY_SUCCESS);
+	return 0;
+}
+
+int CRabbitmqClient::QueueUnbind(const string &strQueueName, const string &strExchange, const string &strBindKey) {
+	if(NULL == m_pConn) {
+		fprintf(stderr, "QueueUnbind m_pConn is null\n");
+		return -1;
+	}
+
+	amqp_channel_open(m_pConn, m_iChannel);
+	amqp_bytes_t _queue = amqp_cstring_bytes(strQueueName.c_str());
+	amqp_bytes_t _exchange = amqp_cstring_bytes(strExchange.c_str());
+	amqp_bytes_t _routkey  = amqp_cstring_bytes(strBindKey.c_str());
+	amqp_queue_unbind(m_pConn, m_iChannel, _queue, _exchange, _routkey, amqp_empty_table);
+	if(0 != ErrorMsg(amqp_get_rpc_reply(m_pConn), "queue_unbind")) {
+		amqp_channel_close(m_pConn, m_iChannel, AMQP_REPLY_SUCCESS);
+		return -1;
+	}
+
+	amqp_channel_close(m_pConn, m_iChannel, AMQP_REPLY_SUCCESS);
+	return 0;
+}
+
+int CRabbitmqClient::QueueDelete(const string &strQueueName, int iIfUnused) {
+	if(NULL == m_pConn) {
+		fprintf(stderr, "QueueDelete m_pConn is null\n");
+		return -1;
+	}
+
+	amqp_channel_open(m_pConn, m_iChannel);
+	if(0 != ErrorMsg(amqp_get_rpc_reply(m_pConn), "open channel")) {
+		amqp_channel_close(m_pConn, m_iChannel, AMQP_REPLY_SUCCESS);
+		return -2;
+	}
+
+	amqp_queue_delete(m_pConn, m_iChannel, amqp_cstring_bytes(strQueueName.c_str()), iIfUnused, 0);
+	if(0 != ErrorMsg(amqp_get_rpc_reply(m_pConn), "delete queue")) {
+		amqp_channel_close(m_pConn, m_iChannel, AMQP_REPLY_SUCCESS);
+		return -3;
+	}
+
+	amqp_channel_close(m_pConn, m_iChannel, AMQP_REPLY_SUCCESS);
+	return 0;
+}
+
+int CRabbitmqClient::Publish(const string &strMessage, const string &strExchange, const string &strRoutekey) {
+	if (NULL == m_pConn) {
+		fprintf(stderr, "publish m_pConn is null, publish failed\n");
+		return -1;
+	}
+
+	amqp_channel_open(m_pConn, m_iChannel);
+	if(0 != ErrorMsg(amqp_get_rpc_reply(m_pConn), "open channel")) {
+		amqp_channel_close(m_pConn, m_iChannel, AMQP_REPLY_SUCCESS);
+		return -2;
+	}
+
+	amqp_bytes_t message_bytes;
+	message_bytes.len = strMessage.length();
+	message_bytes.bytes = (void *)(strMessage.c_str());
+	//fprintf(stderr, "publish message(%d): %.*s\n", (int)message_bytes.len, (int)message_bytes.len, (char *)message_bytes.bytes);
+
+	/*
+	amqp_basic_properties_t props;
+	props._flags = AMQP_BASIC_CONTENT_TYPE_FLAG | AMQP_BASIC_DELIVERY_MODE_FLAG;
+	props.content_type = amqp_cstring_bytes(m_type.c_str());
+	props.delivery_mode = m_durable;    // persistent delivery mode
+	*/
+
+	amqp_bytes_t exchange = amqp_cstring_bytes(strExchange.c_str());
+	amqp_bytes_t routekey = amqp_cstring_bytes(strRoutekey.c_str());
+
+	//if (0 != amqp_basic_publish(m_pConn, m_iChannel, exchange, routekey, 0, 0, &props, message_bytes)) {
+	if (0 != amqp_basic_publish(m_pConn, m_iChannel, exchange, routekey, 0, 0, NULL, message_bytes)) {
+		fprintf(stderr, "publish amqp_basic_publish failed\n");
+		if (0 != ErrorMsg(amqp_get_rpc_reply(m_pConn), "amqp_basic_publish")) {
+			amqp_channel_close(m_pConn, m_iChannel, AMQP_REPLY_SUCCESS);
+			return -3;
+		}
+	}
+
+	amqp_channel_close(m_pConn, m_iChannel, AMQP_REPLY_SUCCESS);
+	return 0;
+}
+
+int CRabbitmqClient::Consumer(const string &strQueueName, vector<string> &message_array, int GetNum, struct timeval *timeout) {
+	if (NULL == m_pConn) {
+		fprintf(stderr, "Consumer m_pConn is null, Consumer failed\n");
+		return -1;
+	}
+
+	amqp_channel_open(m_pConn, m_iChannel);
+	if (0 != ErrorMsg(amqp_get_rpc_reply(m_pConn), "open channel")) {
+		amqp_channel_close(m_pConn, m_iChannel, AMQP_REPLY_SUCCESS);
+		return -2;
+	}
+
+	amqp_basic_qos(m_pConn, m_iChannel, 0, GetNum, 0);
+	int ack = 1; // no_ack    是否需要确认消息后再从队列中删除消息
+	amqp_bytes_t queuename= amqp_cstring_bytes(strQueueName.c_str());
+	amqp_basic_consume(m_pConn, m_iChannel, queuename, amqp_empty_bytes, 0, ack, 0, amqp_empty_table);
+
+	if (0 != ErrorMsg(amqp_get_rpc_reply(m_pConn), "Consuming")) {
+		amqp_channel_close(m_pConn, m_iChannel, AMQP_REPLY_SUCCESS);
+		return -3;
+	}
+
+	int hasget = 0;
+	amqp_rpc_reply_t res;
+	amqp_envelope_t envelope;
+	while (GetNum > 0) {
+		amqp_maybe_release_buffers(m_pConn);
+		res = amqp_consume_message(m_pConn, &envelope, timeout, 0);
+		if (AMQP_RESPONSE_NORMAL != res.reply_type) {
+			fprintf(stderr, "Consumer amqp_channel_close failed\n");
+			amqp_channel_close(m_pConn, m_iChannel, AMQP_REPLY_SUCCESS);
+
+			if (0 == hasget)
+				return -res.reply_type;
+			else
+				return 0;
+		}
+
+		string str((char *)envelope.message.body.bytes, (char *)envelope.message.body.bytes + envelope.message.body.len);
+		message_array.push_back(str);
+		int rtn = amqp_basic_ack(m_pConn, m_iChannel, envelope.delivery_tag, 1);
+		amqp_destroy_envelope(&envelope);
+		if (rtn != 0) {
+			amqp_channel_close(m_pConn, m_iChannel, AMQP_REPLY_SUCCESS);
+			return -4;
+		}
+
+		GetNum--;
+		hasget++;
+		usleep(1);
+	}
+
+	return 0;
+}
+
+int CRabbitmqClient::ErrorMsg(amqp_rpc_reply_t x, char const *context) {
+	switch (x.reply_type) {
+		case AMQP_RESPONSE_NORMAL:
+			return 0;
+
+		case AMQP_RESPONSE_NONE:
+			fprintf(stderr, "%s: missing RPC reply type!\n", context);
+			break;
+
+		case AMQP_RESPONSE_LIBRARY_EXCEPTION:
+			fprintf(stderr, "%s: %s\n", context, amqp_error_string2(x.library_error));
+			break;
+
+		case AMQP_RESPONSE_SERVER_EXCEPTION:
+			switch (x.reply.id) {
+				case AMQP_CONNECTION_CLOSE_METHOD: {
+					amqp_connection_close_t *m = (amqp_connection_close_t *)x.reply.decoded;
+					fprintf(stderr, "%s: server connection error %uh, message: %.*s\n",
+							context, m->reply_code, (int)m->reply_text.len,
+							(char *)m->reply_text.bytes);
+					break;
+				}
+				case AMQP_CHANNEL_CLOSE_METHOD: {
+					amqp_channel_close_t *m = (amqp_channel_close_t *)x.reply.decoded;
+					fprintf(stderr, "%s: server channel error %uh, message: %.*s\n",
+							context, m->reply_code, (int)m->reply_text.len,
+							(char *)m->reply_text.bytes);
+					break;
+				}
+				default:
+					fprintf(stderr, "%s: unknown server error, method id 0x%08X\n",
+							context, x.reply.id);
+					break;
+			}
+			break;
+	}
+
+	return -1;
+}

+ 105 - 0
plc调度节点/rabbitmq/ttt.h

@@ -0,0 +1,105 @@
+#ifndef RABBITMQ_CLIENT_H_
+#define RABBITMQ_CLIENT_H_
+
+
+#include <string>
+#include <vector>
+
+#include <rabbitmq-c/tcp_socket.h>
+
+using std::string;
+using std::vector;
+
+class CRabbitmqClient{
+public:
+	CRabbitmqClient();
+	~CRabbitmqClient();
+
+
+	int Connect(const string &strHostname, int iPort, const string &strUser, const string &strPasswd);
+	int Disconnect();
+
+	/**
+	*   @brief       ExchangeDeclare    声明exchange
+	*	@param       [in]               strExchange
+	*   @param       [in]               strType
+	*   @return 等于0值代表成功创建exchange,小于0代表错误
+	*/
+	int ExchangeDeclare(const string &strExchange, const string &strType);
+
+	/**
+	*   @brief       QueueDeclare                     声明消息队列
+	*	@param       [in]               strQueueName  消息队列实例
+	*   @param
+	*   @return 等于0值代表成功创建queue,小于0代表错误
+	*/
+	int QueueDeclare(const string &strQueueName);
+
+	/**
+	*   @brief       QueueBind                        将队列,交换机和绑定规则绑定起来形成一个路由表
+	*	@param       [in]               strQueueName  消息队列
+	*	@param       [in]               strExchange   交换机名称
+	*	@param       [in]               strBindKey    路由名称  “msg.#” “msg.weather.**”
+	*   @return 等于0值代表成功绑定,小于0代表错误
+	*/
+	int QueueBind(const string &strQueueName, const string &strExchange, const string &strBindKey);
+
+	/**
+	*   @brief       QueueUnbind                      将队列,交换机和绑定规则绑定解除
+	*	@param       [in]               strQueueName  消息队列
+	*	@param       [in]               strExchange   交换机名称
+	*	@param       [in]               strBindKey    路由名称  “msg.#” “msg.weather.**”
+	*   @return 等于0值代表成功绑定,小于0代表错误
+	*/
+	int QueueUnbind(const string &strQueueName, const string &strExchange, const string &strBindKey);
+
+	/**
+	*   @brief       QueueDelete                      删除消息队列。
+	*	@param       [in]               strQueueName  消息队列名称
+	*	@param       [in]               iIfUnused     消息队列是否在用,1 则论是否在用都删除
+	*   @return 等于0值代表成功删除queue,小于0代表错误
+	*/
+	int QueueDelete(const string &strQueueName, int iIfUnused);
+
+	/**
+	* @brief Publish  发布消息
+	* @param [in] strMessage        消息实体
+	* @param [in] strExchange       交换器
+	* @param [in] strRoutekey       路由规则
+	*   1.Direct Exchange – 处理路由键。需要将一个队列绑定到交换机上,要求该消息与一个特定的路由键完全匹配。
+	*   2.Fanout Exchange – 不处理路由键。将队列绑定到交换机上。一个发送到交换机的消息都会被转发到与该交换机绑定的所有队列上。
+	*   3.Topic Exchange – 将路由键和某模式进行匹配。此时队列需要绑定要一个模式上。符号“#”匹配一个或多个词,符号“*”匹配不多不少一个词。
+	*      因此“audit.#”能够匹配到“audit.irs.corporate”,但是“audit.*” 只会匹配到“audit.irs”
+	* @return 等于0值代表成功发送消息实体,小于0代表发送错误
+	*/
+	int Publish(const string &strMessage, const string &strExchange, const string &strRoutekey);
+
+	/**
+	* @brief consumer  消费消息
+	* @param [in]  strQueueName         队列名称
+	* @param [out] message_array        获取的消息实体
+	* @param [int] GetNum               需要取得的消息个数
+	* @param [int] timeout              取得的消息是延迟,若为NULL,表示持续取,无延迟,阻塞状态
+	* @return 等于0值代表成功,小于0代表错误,错误信息从ErrorReturn返回
+	*/
+	int Consumer(const string &strQueueName, vector<string> &message_array, int GetNum = 1, struct timeval *timeout = NULL);
+
+
+private:
+	CRabbitmqClient(const CRabbitmqClient & rh);
+	void operator=(const CRabbitmqClient & rh);
+
+	int ErrorMsg(amqp_rpc_reply_t x, char const *context);
+
+
+	string                      m_strHostname;      // amqp主机
+	int                         m_iPort;            // amqp端口
+	string					    m_strUser;
+	string					    m_strPasswd;
+	int                         m_iChannel;
+
+	amqp_socket_t               *m_pSock;
+	amqp_connection_state_t     m_pConn;
+};
+
+#endif

+ 79 - 0
plc调度节点/rabbitmq/胡力的rabbitmq-c说明文档.md

@@ -0,0 +1,79 @@
+
+
+安装 rabbitMQ-c 的注意事项:(这里只介绍C语言版本的客户端)
+
+1.代码下载
+	rabbitMQ官网 		https://www.rabbitmq.com/
+	各种语言支持			https://www.rabbitmq.com/devtools.html
+		里面有C/C++的支持
+	github上源码			https://github.com/alanxz/rabbitmq-c
+
+2.安装方式
+	终端指令:注意了,要用sudo使用管理员权限
+	git clone https://github.com/alanxz/rabbitmq-c  
+	cd rabbitmq-c
+	mkdir build
+	cd build
+	sudo cmake ..
+	sudo cmake --build .
+	sudo make 
+	sudo make install
+
+	详情参考		https://blog.csdn.net/caicaiatnbu/article/details/98099779?ops_request_misc=&request_id=&biz_id=102&utm_term=RabbitMQ-C&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-3-98099779.nonecase&spm=1018.2226.3001.4187
+
+	如果提示openssl有报错,卸载并重装openssl
+	详情参考		https://blog.csdn.net/Cai181191/article/details/120648055?ops_request_misc=&request_id=&biz_id=102&utm_term=%E5%8D%B8%E8%BD%BDopenssl&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-1-120648055.142^v41^pc_rank_34,185^v2^control&spm=1018.2226.3001.4187
+
+3.examples代码编译
+	方案一:不建议
+	打开		./rabbitmq-c/CMakeLists.txt
+		找到		option(BUILD_EXAMPLES "Build Examples" OFF)
+		修改为	option(BUILD_EXAMPLES "Build Examples" ON)
+	然后重新编译 ./rabbitmq-c/CMakeLists.txt  就是把上面第二步再做一遍
+		cd ./rabbitmq-c/build
+		sudo cmake ..
+		sudo cmake --build .
+		sudo make 
+	然后就可以看到	./rabbitmq-c/build/examples 路径下面出现了样例的执行文件
+
+	方案二:强烈推荐
+	进入		./rabbitmq-c/examples 文件夹	,后面的操作都在这个文件夹里面
+	打开		./rabbitmq-c/examples/CMakeLists.txt
+	全局替换		rabbitmq::rabbitmq   改为	rabbitmq
+	就是删除 rabbitmq::
+	然后 编译 ./rabbitmq-c/examples/CMakeLists.txt
+		cd ./rabbitmq-c/examples/
+		mkdir build
+		cd build
+		cmake ..
+		make 
+	然后就可以看到	./rabbitmq-c/examples/build 路径下面出现了样例的执行文件
+
+4.自己开发rabbitMQ-c代码
+	在自己的  CMakeLists.txt  里面 增加系统头文件和库文件的目录.
+	例如:
+		include_directories(
+        /usr/local/include
+		)
+		link_directories("/usr/local/lib")
+
+	在自己的  CMakeLists.txt  里面 target_link_libraries 追加 rabbitmq
+	例如:	
+		target_link_libraries(xxx工程名		rabbitmq )
+
+	具体的函数使用,参考examples里面的amqp_listen.c和amqp_sendstring.c
+
+5.服务器网站配置
+	登录服务器   http://127.0.0.1:15672/     或者     http://192.168.2.39:15672/
+		默认账号密码   guest   guest    (注, guest只能本机访问,其他电脑需要新建账户)
+	
+	终端指令: 使用sudo
+		创建用户 rabbitmqctl add_user admin admin
+		设置管理员 rabbitmqctl set_user_tags admin administrator
+		设置权限  rabbitmqctl set_permissions -p/admin ".*"".*"".*"
+		查看用户  rabbitmqctl list_users
+		详见  https://blog.csdn.net/z446981439/article/details/103634524?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522166141324016782388032414%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=166141324016782388032414&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduend~default-2-103634524-null-null.142^v42^pc_rank_34,185^v2^control&utm_term=rabbitmq%20%E7%94%A8%E6%88%B7&spm=1018.2226.3001.4187
+
+		个人建议:只在终端上创建账户,然后使用guest在网站上面配置权限.
+	
+	

+ 14 - 0
plc调度节点/run_dispatch.sh

@@ -0,0 +1,14 @@
+#!/bin/bash
+ 
+
+{
+gnome-terminal -x bash -c "cd ./build/&&./terminal 0; exec bash"
+}&
+ 
+{
+gnome-terminal -x bash -c "cd ./build/&&./terminal 1; exec bash"
+}&
+
+{
+gnome-terminal -x bash -c "cd ./build/&&./terminal 2; exec bash"
+}&

+ 55 - 0
plc调度节点/setting/communication.prototxt

@@ -0,0 +1,55 @@
+
+
+communication_parameters
+{
+
+#   bind_string:"tcp://192.168.2.166:9000"
+ #  connect_string_vector:"tcp://192.168.2.166:9001"
+ # connect_string_vector:"tcp://192.168.2.166:9002"
+
+  # connect_string_vector:"tcp://192.168.2.125:9876"
+  # connect_string_vector:"tcp://192.168.2.166:1234"
+
+  # bind_string:"tcp://192.168.2.166:4444"
+  #      bind_string:"tcp://192.168.3.106:5555"
+
+#    bind_string:"tcp://192.168.2.192:30002"
+
+
+
+ #  bind_string:"tcp://192.168.2.167:30002"
+  # connect_string_vector:"tcp://192.168.2.183:30003"
+ #  connect_string_vector:"tcp://192.168.2.183:30000"
+
+
+ #   connect_string_vector:"tcp://192.168.2.233:30000"
+
+ #   connect_string_vector:"tcp://192.168.2.165:30000"
+ #   bind_string:"tcp://192.168.2.177:30009"
+
+  #  connect_string_vector:"tcp://192.168.2.127:30001"
+
+#    connect_string_vector:"tcp://192.168.2.174:30002"
+
+
+
+    connect_string_vector:"tcp://192.168.2.233:30000"
+    connect_string_vector:"tcp://192.168.2.233:30010"
+
+    connect_string_vector:"tcp://192.168.2.180:30009"
+    connect_string_vector:"tcp://192.168.2.181:30009"
+    connect_string_vector:"tcp://192.168.2.182:30009"
+    connect_string_vector:"tcp://192.168.2.183:30009"
+    connect_string_vector:"tcp://192.168.2.184:30009"
+    connect_string_vector:"tcp://192.168.2.185:30009"
+
+    connect_string_vector:"tcp://192.168.2.186:30009"
+    connect_string_vector:"tcp://192.168.2.187:30009"
+
+    connect_string_vector:"tcp://192.168.2.245:30009"
+    connect_string_vector:"tcp://192.168.2.233:30009"
+
+    connect_string_vector:"tcp://192.168.2.164:30009"
+
+}
+

+ 54 - 0
plc调度节点/setting/communication_a.prototxt

@@ -0,0 +1,54 @@
+
+
+communication_parameters
+{
+
+#   bind_string:"tcp://192.168.2.166:9000"
+ #  connect_string_vector:"tcp://192.168.2.166:9001"
+ # connect_string_vector:"tcp://192.168.2.166:9002"
+
+  # connect_string_vector:"tcp://192.168.2.125:9876"
+  # connect_string_vector:"tcp://192.168.2.166:1234"
+
+  # bind_string:"tcp://192.168.2.166:4444"
+  #      bind_string:"tcp://192.168.3.106:5555"
+
+#    bind_string:"tcp://192.168.2.192:30002"
+
+
+
+ #  bind_string:"tcp://192.168.2.167:30002"
+  # connect_string_vector:"tcp://192.168.2.183:30003"
+ #  connect_string_vector:"tcp://192.168.2.183:30000"
+
+
+ #   connect_string_vector:"tcp://192.168.2.233:30000"
+
+ #   connect_string_vector:"tcp://192.168.2.165:30000"
+ #   bind_string:"tcp://192.168.2.177:30009"
+
+  #  connect_string_vector:"tcp://192.168.2.127:30001"
+
+#    connect_string_vector:"tcp://192.168.2.174:30002"
+
+
+    bind_string:"tcp://192.168.1.233:30030"
+    connect_string_vector:"tcp://192.168.1.233:30000"
+    connect_string_vector:"tcp://192.168.1.233:30010"
+
+    connect_string_vector:"tcp://192.168.1.180:30009"
+    connect_string_vector:"tcp://192.168.1.181:30009"
+    connect_string_vector:"tcp://192.168.1.182:30009"
+    connect_string_vector:"tcp://192.168.1.183:30009"
+    connect_string_vector:"tcp://192.168.1.184:30009"
+    connect_string_vector:"tcp://192.168.1.185:30009"
+
+    connect_string_vector:"tcp://192.168.1.186:30009"
+    connect_string_vector:"tcp://192.168.1.187:30009"
+
+    connect_string_vector:"tcp://192.168.1.245:30009"
+    connect_string_vector:"tcp://192.168.1.233:30009"
+
+
+}
+

+ 54 - 0
plc调度节点/setting/communication_b.prototxt

@@ -0,0 +1,54 @@
+
+
+communication_parameters
+{
+
+#   bind_string:"tcp://192.168.2.166:9000"
+ #  connect_string_vector:"tcp://192.168.2.166:9001"
+ # connect_string_vector:"tcp://192.168.2.166:9002"
+
+  # connect_string_vector:"tcp://192.168.2.125:9876"
+  # connect_string_vector:"tcp://192.168.2.166:1234"
+
+  # bind_string:"tcp://192.168.2.166:4444"
+  #      bind_string:"tcp://192.168.3.106:5555"
+
+#    bind_string:"tcp://192.168.2.192:30002"
+
+
+
+ #  bind_string:"tcp://192.168.2.167:30002"
+  # connect_string_vector:"tcp://192.168.2.183:30003"
+ #  connect_string_vector:"tcp://192.168.2.183:30000"
+
+
+ #   connect_string_vector:"tcp://192.168.2.233:30000"
+
+ #   connect_string_vector:"tcp://192.168.2.165:30000"
+ #   bind_string:"tcp://192.168.2.177:30009"
+
+  #  connect_string_vector:"tcp://192.168.2.127:30001"
+
+#    connect_string_vector:"tcp://192.168.2.174:30002"
+
+
+    bind_string:"tcp://192.168.1.233:30031"
+    connect_string_vector:"tcp://192.168.1.233:30000"
+    connect_string_vector:"tcp://192.168.1.233:30010"
+
+    connect_string_vector:"tcp://192.168.1.180:30009"
+    connect_string_vector:"tcp://192.168.1.181:30009"
+    connect_string_vector:"tcp://192.168.1.182:30009"
+    connect_string_vector:"tcp://192.168.1.183:30009"
+    connect_string_vector:"tcp://192.168.1.184:30009"
+    connect_string_vector:"tcp://192.168.1.185:30009"
+
+    connect_string_vector:"tcp://192.168.1.186:30009"
+    connect_string_vector:"tcp://192.168.1.187:30009"
+
+    connect_string_vector:"tcp://192.168.1.245:30009"
+    connect_string_vector:"tcp://192.168.1.233:30009"
+
+
+}
+

+ 54 - 0
plc调度节点/setting/communication_c.prototxt

@@ -0,0 +1,54 @@
+
+
+communication_parameters
+{
+
+#   bind_string:"tcp://192.168.2.166:9000"
+ #  connect_string_vector:"tcp://192.168.2.166:9001"
+ # connect_string_vector:"tcp://192.168.2.166:9002"
+
+  # connect_string_vector:"tcp://192.168.2.125:9876"
+  # connect_string_vector:"tcp://192.168.2.166:1234"
+
+  # bind_string:"tcp://192.168.2.166:4444"
+  #      bind_string:"tcp://192.168.3.106:5555"
+
+#    bind_string:"tcp://192.168.2.192:30002"
+
+
+
+ #  bind_string:"tcp://192.168.2.167:30002"
+  # connect_string_vector:"tcp://192.168.2.183:30003"
+ #  connect_string_vector:"tcp://192.168.2.183:30000"
+
+
+ #   connect_string_vector:"tcp://192.168.2.233:30000"
+
+ #   connect_string_vector:"tcp://192.168.2.165:30000"
+ #   bind_string:"tcp://192.168.2.177:30009"
+
+  #  connect_string_vector:"tcp://192.168.2.127:30001"
+
+#    connect_string_vector:"tcp://192.168.2.174:30002"
+
+
+    bind_string:"tcp://192.168.2.233:30032"
+    connect_string_vector:"tcp://192.168.1.233:30000"
+    connect_string_vector:"tcp://192.168.1.233:30010"
+
+    connect_string_vector:"tcp://192.168.1.180:30009"
+    connect_string_vector:"tcp://192.168.1.181:30009"
+    connect_string_vector:"tcp://192.168.1.182:30009"
+    connect_string_vector:"tcp://192.168.1.183:30009"
+    connect_string_vector:"tcp://192.168.1.184:30009"
+    connect_string_vector:"tcp://192.168.1.185:30009"
+
+    connect_string_vector:"tcp://192.168.1.186:30009"
+    connect_string_vector:"tcp://192.168.1.187:30009"
+
+    connect_string_vector:"tcp://192.168.1.245:30009"
+    connect_string_vector:"tcp://192.168.1.233:30009"
+
+
+}
+

+ 20 - 0
plc调度节点/setting/database_communication.prototxt

@@ -0,0 +1,20 @@
+
+database_communication_configurations
+{
+    db_ip:"192.168.1.233",
+    db_port:3306,
+    db_username:"zx",
+    db_passwd:"zx123456",
+    db_name:"ct_project",
+    db_conn_pool_size:5
+}
+#database_communication_configurations
+#{
+#    db_ip:"127.0.0.1",
+#    db_port:3306,
+#    db_username:"zx",
+ #  db_passwd:"zx123456",
+ #   db_name:"chutian_parkingspace",
+#    db_conn_pool_size:5
+#}
+

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 3384 - 0
plc调度节点/setting/dispatch_coordinates.prototxt


+ 33 - 0
plc调度节点/setting/dispatch_device.prototxt

@@ -0,0 +1,33 @@
+
+
+
+catcher_size:1
+catcher_parameters
+{
+    id:1
+    key:102
+}
+
+carrier_size:3
+carrier_parameters
+{
+    id:0
+    key:200
+}
+carrier_parameters
+{
+    id:1
+    key:207
+}
+carrier_parameters
+{
+    id:2
+    key:203
+}
+
+passageway_size:0
+
+
+
+
+

+ 86 - 0
plc调度节点/setting/laser.prototxt

@@ -0,0 +1,86 @@
+#1号雷达
+#  0TFDFG700601881  0TFDFCE00502001 0TFDH5L00684HE1  0TFDH5R006RCJ91
+
+
+
+
+laser_parameters
+{
+	type:"Livox"
+	sn:"0TFDFG700601881"
+	frame_num:1000
+    mat_r00:1
+    mat_r01:0
+    mat_r02:0
+    mat_r03:0
+    mat_r10:0
+    mat_r11:1
+    mat_r12:0
+    mat_r13:0
+    mat_r20:0
+    mat_r21:0
+    mat_r22:1
+    mat_r23:0
+}
+
+
+laser_parameters
+{
+	type:"Livox"
+	sn:"0TFDFCE00502001"
+	frame_num:1000
+    mat_r00:1
+    mat_r01:0
+    mat_r02:0
+    mat_r03:0
+    mat_r10:0
+    mat_r11:1
+    mat_r12:0
+    mat_r13:0
+    mat_r20:0
+    mat_r21:0
+    mat_r22:1
+    mat_r23:0
+}
+
+
+
+laser_parameters
+{
+	type:"Livox"
+	sn:"0TFDH5L00684HE1"
+	frame_num:1000
+    mat_r00:1
+    mat_r01:0
+    mat_r02:0
+    mat_r03:0
+    mat_r10:0
+    mat_r11:1
+    mat_r12:0
+    mat_r13:0
+    mat_r20:0
+    mat_r21:0
+    mat_r22:1
+    mat_r23:0
+}
+
+
+
+laser_parameters
+{
+	type:"Livox"
+	sn:"0TFDH5R006RCJ91"
+	frame_num:1000
+    mat_r00:1
+    mat_r01:0
+    mat_r02:0
+    mat_r03:0
+    mat_r10:0
+    mat_r11:1
+    mat_r12:0
+    mat_r13:0
+    mat_r20:0
+    mat_r21:0
+    mat_r22:1
+    mat_r23:0
+}

+ 54 - 0
plc调度节点/setting/locate.prototxt

@@ -0,0 +1,54 @@
+area{
+ #   x_min:-1227.5
+ #   x_max:1802.9
+ #   y_min:-2789.8
+ #   y_max:3777.19
+  #  z_min:0
+  #  z_max:1800
+
+        x_min:-1000000
+        x_max:1000000
+        y_min:-1000000
+        y_max:1000000
+        z_min:-1000000
+        z_max:1000000
+}
+
+net_3dcnn_parameter
+{
+    length:0.224
+    width:0.224
+    height:0.096
+    freq:0.025
+    nclass:3
+    weights_file:"./setting/3dcnn_model.pb"
+}
+
+seg_parameter
+{
+    point_size:8192
+    cls_num:2
+    freq:0.020
+    area
+    {
+        x_min:-100000.0
+    	x_max:100000.0
+    	y_min:-100000.0
+    	y_max:100000.0
+    	z_min:-100000.0
+    	z_max:100000.0
+    }
+    graph:"../model_param/seg_model_404500.ckpt.meta"
+    cpkt:"../model_param/seg_model_404500.ckpt"
+}
+
+yolo_parameter
+{
+    cfg:"./setting/yolov3-spot2.cfg"
+    weights:"./setting/yolov3-spot2_12000.weights"
+    min_x:-1227.5
+    max_x:10802.9
+    min_y:-2789.8
+    max_y:3777.19
+    freq:25.
+}

+ 183 - 0
plc调度节点/setting/rabbitmq.prototxt

@@ -0,0 +1,183 @@
+
+
+rabbitmq_parameters
+{
+    ip:"192.168.1.233"
+    port:5672
+    user:"zx"
+    password:"zx123456"
+
+
+#   rabbitmq_reciever_vector
+#    {
+#        channel:411
+#        exchange_name:"command_ex"
+#
+#        binding_key:"count_command_signal_1_port"
+#        queue_name:"count_command_signal_1_queue"
+#        queue_passive:0
+#        queue_durable:1
+#        queue_exclusive:0
+#        queue_auto_delete:0
+#        consume_name:"count_command_signal_1_consume"
+#        consume_no_local:0
+#        consume_no_ack:0
+#        consume_exclusive:0
+#    }
+#    rabbitmq_reciever_vector
+#    {
+#        channel:421
+#        exchange_name:"command_ex"
+#
+#        binding_key:"post_command_1_port"
+#        queue_name:"post_command_1_queue"
+#        queue_passive:0
+#        queue_durable:1
+#        queue_exclusive:0
+#        queue_auto_delete:0
+#        consume_name:"post_command_1_consume"
+#        consume_no_local:0
+#        consume_no_ack:0
+#        consume_exclusive:0
+#    }
+
+
+
+    rabbitmq_reciever_vector
+    {
+       channel:601
+       exchange_name:"statu_ex"
+
+       binding_key:"measure_1_statu_port"
+       queue_name:"measure_1_statu_queue_for_dispatch"
+       queue_passive:0
+       queue_durable:0
+       queue_exclusive:0
+       queue_auto_delete:1
+       queue_meassage_ttl:1000
+       consume_name:"measure_1_statu_consume_for_dispatch"
+       consume_no_local:0
+       consume_no_ack:1
+       consume_exclusive:0
+    }
+
+    rabbitmq_reciever_vector
+    {
+        channel:602
+        exchange_name:"statu_ex"
+
+        binding_key:"measure_2_statu_port"
+        queue_name:"measure_2_statu_queue_for_dispatch"
+        queue_passive:0
+        queue_durable:0
+        queue_exclusive:0
+        queue_auto_delete:1
+       queue_meassage_ttl:1000
+        consume_name:"measure_2_statu_consume_for_dispatch"
+        consume_no_local:0
+        consume_no_ack:1
+        consume_exclusive:0
+    }
+
+    rabbitmq_reciever_vector
+    {
+        channel:701
+        exchange_name:"statu_ex"
+
+        binding_key:"in_mcpu_1_statu_port"
+        queue_name:"in_mcpu_1_statu_queue_for_dispatch"
+        queue_passive:0
+        queue_durable:0
+        queue_exclusive:0
+        queue_auto_delete:1
+       queue_meassage_ttl:1000
+        consume_name:"in_mcpu_1_statu_consume_for_dispatch"
+        consume_no_local:0
+        consume_no_ack:1
+        consume_exclusive:0
+    }
+
+    rabbitmq_reciever_vector
+    {
+        channel:702
+        exchange_name:"statu_ex"
+
+        binding_key:"in_mcpu_2_statu_port"
+        queue_name:"in_mcpu_2_statu_queue_for_dispatch"
+        queue_passive:0
+        queue_durable:0
+        queue_exclusive:0
+        queue_auto_delete:1
+       queue_meassage_ttl:1000
+        consume_name:"in_mcpu_2_statu_consume_for_dispatch"
+        consume_no_local:0
+        consume_no_ack:1
+        consume_exclusive:0
+    }
+
+    rabbitmq_reciever_vector
+    {
+        channel:801
+        exchange_name:"statu_ex"
+
+        binding_key:"out_mcpu_1_statu_port"
+        queue_name:"out_mcpu_1_statu_queue_for_dispatch"
+        queue_passive:0
+        queue_durable:0
+        queue_exclusive:0
+        queue_auto_delete:1
+       queue_meassage_ttl:1000
+        consume_name:"out_mcpu_1_statu_consume_for_dispatch"
+        consume_no_local:0
+        consume_no_ack:1
+        consume_exclusive:0
+    }
+
+    rabbitmq_reciever_vector
+    {
+        channel:802
+        exchange_name:"statu_ex"
+
+        binding_key:"out_mcpu_2_statu_port"
+        queue_name:"out_mcpu_2_statu_queue_for_dispatch"
+        queue_passive:0
+        queue_durable:0
+        queue_exclusive:0
+        queue_auto_delete:1
+       queue_meassage_ttl:1000
+        consume_name:"out_mcpu_2_statu_consume_for_dispatch"
+        consume_no_local:0
+        consume_no_ack:1
+        consume_exclusive:0
+    }
+
+
+
+
+
+
+    rabbitmq_sender_request_vector
+    {
+        channel:431
+        exchange_name:"command_ex"
+        routing_key:"request_command_port"
+        timeout_ms:0
+    }
+
+    rabbitmq_sender_request_vector
+    {
+        channel:441
+        exchange_name:"command_ex"
+        routing_key:"command_completed_port"
+        timeout_ms:0
+    }
+
+    rabbitmq_sender_status_vector
+    {
+        channel:451
+        exchange_name:"statu_ex"
+        routing_key:"dispatch_1_statu_port"
+        timeout_ms:10000
+    }
+
+}

+ 183 - 0
plc调度节点/setting/rabbitmq_a.prototxt

@@ -0,0 +1,183 @@
+
+
+rabbitmq_parameters
+{
+    ip:"192.168.1.233"
+    port:5672
+    user:"zx"
+    password:"zx123456"
+
+
+#   rabbitmq_reciever_vector
+#    {
+#        channel:411
+#        exchange_name:"command_ex"
+#
+#        binding_key:"count_command_signal_1_port"
+#        queue_name:"count_command_signal_1_queue"
+#        queue_passive:0
+#        queue_durable:1
+#        queue_exclusive:0
+#        queue_auto_delete:0
+#        consume_name:"count_command_signal_1_consume"
+#        consume_no_local:0
+#        consume_no_ack:0
+#        consume_exclusive:0
+#    }
+#    rabbitmq_reciever_vector
+#    {
+#        channel:421
+#        exchange_name:"command_ex"
+#
+#        binding_key:"post_command_1_port"
+#        queue_name:"post_command_1_queue"
+#        queue_passive:0
+#        queue_durable:1
+#        queue_exclusive:0
+#        queue_auto_delete:0
+#        consume_name:"post_command_1_consume"
+#        consume_no_local:0
+#        consume_no_ack:0
+#        consume_exclusive:0
+#    }
+
+
+
+    rabbitmq_reciever_vector
+    {
+       channel:601
+       exchange_name:"statu_ex"
+
+       binding_key:"measure_1_statu_port"
+       queue_name:"measure_1_statu_queue_for_dispatch"
+       queue_passive:0
+       queue_durable:0
+       queue_exclusive:0
+       queue_auto_delete:1
+       queue_meassage_ttl:1000
+       consume_name:"measure_1_statu_consume_for_dispatch"
+       consume_no_local:0
+       consume_no_ack:1
+       consume_exclusive:0
+    }
+
+    rabbitmq_reciever_vector
+    {
+        channel:602
+        exchange_name:"statu_ex"
+
+        binding_key:"measure_2_statu_port"
+        queue_name:"measure_2_statu_queue_for_dispatch"
+        queue_passive:0
+        queue_durable:0
+        queue_exclusive:0
+        queue_auto_delete:1
+       queue_meassage_ttl:1000
+        consume_name:"measure_2_statu_consume_for_dispatch"
+        consume_no_local:0
+        consume_no_ack:1
+        consume_exclusive:0
+    }
+
+    rabbitmq_reciever_vector
+    {
+        channel:701
+        exchange_name:"statu_ex"
+
+        binding_key:"in_mcpu_1_statu_port"
+        queue_name:"in_mcpu_1_statu_queue_for_dispatch"
+        queue_passive:0
+        queue_durable:0
+        queue_exclusive:0
+        queue_auto_delete:1
+       queue_meassage_ttl:1000
+        consume_name:"in_mcpu_1_statu_consume_for_dispatch"
+        consume_no_local:0
+        consume_no_ack:1
+        consume_exclusive:0
+    }
+
+    rabbitmq_reciever_vector
+    {
+        channel:702
+        exchange_name:"statu_ex"
+
+        binding_key:"in_mcpu_2_statu_port"
+        queue_name:"in_mcpu_2_statu_queue_for_dispatch"
+        queue_passive:0
+        queue_durable:0
+        queue_exclusive:0
+        queue_auto_delete:1
+       queue_meassage_ttl:1000
+        consume_name:"in_mcpu_2_statu_consume_for_dispatch"
+        consume_no_local:0
+        consume_no_ack:1
+        consume_exclusive:0
+    }
+
+    rabbitmq_reciever_vector
+    {
+        channel:801
+        exchange_name:"statu_ex"
+
+        binding_key:"out_mcpu_1_statu_port"
+        queue_name:"out_mcpu_1_statu_queue_for_dispatch"
+        queue_passive:0
+        queue_durable:0
+        queue_exclusive:0
+        queue_auto_delete:1
+       queue_meassage_ttl:1000
+        consume_name:"out_mcpu_1_statu_consume_for_dispatch"
+        consume_no_local:0
+        consume_no_ack:1
+        consume_exclusive:0
+    }
+
+    rabbitmq_reciever_vector
+    {
+        channel:802
+        exchange_name:"statu_ex"
+
+        binding_key:"out_mcpu_2_statu_port"
+        queue_name:"out_mcpu_2_statu_queue_for_dispatch"
+        queue_passive:0
+        queue_durable:0
+        queue_exclusive:0
+        queue_auto_delete:1
+       queue_meassage_ttl:1000
+        consume_name:"out_mcpu_2_statu_consume_for_dispatch"
+        consume_no_local:0
+        consume_no_ack:1
+        consume_exclusive:0
+    }
+
+
+
+
+
+
+    rabbitmq_sender_request_vector
+    {
+        channel:431
+        exchange_name:"command_ex"
+        routing_key:"request_command_port"
+        timeout_ms:0
+    }
+
+    rabbitmq_sender_request_vector
+    {
+        channel:441
+        exchange_name:"command_ex"
+        routing_key:"command_completed_port"
+        timeout_ms:0
+    }
+
+    rabbitmq_sender_status_vector
+    {
+        channel:451
+        exchange_name:"statu_ex"
+        routing_key:"dispatch_1_statu_port"
+        timeout_ms:10000
+    }
+
+}

+ 185 - 0
plc调度节点/setting/rabbitmq_b.prototxt

@@ -0,0 +1,185 @@
+
+
+rabbitmq_parameters
+{
+    ip:"192.168.1.233"
+    port:5672
+    user:"zx"
+    password:"zx123456"
+
+
+#   rabbitmq_reciever_vector
+#    {
+#        channel:412
+#        exchange_name:"command_ex"
+#
+#        binding_key:"count_command_signal_2_port"
+#        queue_name:"count_command_signal_2_queue"
+#        queue_passive:0
+#        queue_durable:1
+#        queue_exclusive:0
+#        queue_auto_delete:0
+#        consume_name:"count_command_signal_2_consume"
+#        consume_no_local:0
+#        consume_no_ack:0
+#        consume_exclusive:0
+#    }
+#    rabbitmq_reciever_vector
+#    {
+#        channel:422
+#        exchange_name:"command_ex"
+#
+#        binding_key:"post_command_2_port"
+#        queue_name:"post_command_2_queue"
+#        queue_passive:0
+#        queue_durable:1
+#        queue_exclusive:0
+#        queue_auto_delete:0
+#        consume_name:"post_command_2_consume"
+#        consume_no_local:0
+#        consume_no_ack:0
+#        consume_exclusive:0
+#    }
+
+
+
+
+
+    rabbitmq_reciever_vector
+    {
+       channel:603
+       exchange_name:"statu_ex"
+
+       binding_key:"measure_3_statu_port"
+       queue_name:"measure_3_statu_queue_for_dispatch"
+       queue_passive:0
+       queue_durable:0
+       queue_exclusive:0
+       queue_auto_delete:1
+       queue_meassage_ttl:1000
+       consume_name:"measure_3_statu_consume_for_dispatch"
+       consume_no_local:0
+       consume_no_ack:1
+       consume_exclusive:0
+    }
+
+    rabbitmq_reciever_vector
+    {
+        channel:604
+        exchange_name:"statu_ex"
+
+        binding_key:"measure_4_statu_port"
+        queue_name:"measure_4_statu_queue_for_dispatch"
+        queue_passive:0
+        queue_durable:0
+        queue_exclusive:0
+        queue_auto_delete:1
+       queue_meassage_ttl:1000
+        consume_name:"measure_4_statu_consume_for_dispatch"
+        consume_no_local:0
+        consume_no_ack:1
+        consume_exclusive:0
+    }
+
+    rabbitmq_reciever_vector
+    {
+        channel:703
+        exchange_name:"statu_ex"
+
+        binding_key:"in_mcpu_3_statu_port"
+        queue_name:"in_mcpu_3_statu_queue_for_dispatch"
+        queue_passive:0
+        queue_durable:0
+        queue_exclusive:0
+        queue_auto_delete:1
+       queue_meassage_ttl:1000
+        consume_name:"in_mcpu_3_statu_consume_for_dispatch"
+        consume_no_local:0
+        consume_no_ack:1
+        consume_exclusive:0
+    }
+
+    rabbitmq_reciever_vector
+    {
+        channel:704
+        exchange_name:"statu_ex"
+
+        binding_key:"in_mcpu_4_statu_port"
+        queue_name:"in_mcpu_4_statu_queue_for_dispatch"
+        queue_passive:0
+        queue_durable:0
+        queue_exclusive:0
+        queue_auto_delete:1
+       queue_meassage_ttl:1000
+        consume_name:"in_mcpu_4_statu_consume_for_dispatch"
+        consume_no_local:0
+        consume_no_ack:1
+        consume_exclusive:0
+    }
+
+    rabbitmq_reciever_vector
+    {
+        channel:803
+        exchange_name:"statu_ex"
+
+        binding_key:"out_mcpu_3_statu_port"
+        queue_name:"out_mcpu_3_statu_queue_for_dispatch"
+        queue_passive:0
+        queue_durable:0
+        queue_exclusive:0
+        queue_auto_delete:1
+       queue_meassage_ttl:1000
+        consume_name:"out_mcpu_3_statu_consume_for_dispatch"
+        consume_no_local:0
+        consume_no_ack:1
+        consume_exclusive:0
+    }
+
+    rabbitmq_reciever_vector
+    {
+        channel:804
+        exchange_name:"statu_ex"
+
+        binding_key:"out_mcpu_4_statu_port"
+        queue_name:"out_mcpu_4_statu_queue_for_dispatch"
+        queue_passive:0
+        queue_durable:0
+        queue_exclusive:0
+        queue_auto_delete:1
+       queue_meassage_ttl:1000
+        consume_name:"out_mcpu_4_statu_consume_for_dispatch"
+        consume_no_local:0
+        consume_no_ack:1
+        consume_exclusive:0
+    }
+
+
+
+
+
+
+    rabbitmq_sender_request_vector
+    {
+        channel:432
+        exchange_name:"command_ex"
+        routing_key:"request_command_port"
+        timeout_ms:0
+    }
+
+    rabbitmq_sender_request_vector
+    {
+        channel:442
+        exchange_name:"command_ex"
+        routing_key:"command_completed_port"
+        timeout_ms:0
+    }
+
+    rabbitmq_sender_status_vector
+    {
+        channel:452
+        exchange_name:"statu_ex"
+        routing_key:"dispatch_2_statu_port"
+        timeout_ms:10000
+    }
+
+}

+ 185 - 0
plc调度节点/setting/rabbitmq_c.prototxt

@@ -0,0 +1,185 @@
+
+
+rabbitmq_parameters
+{
+    ip:"192.168.1.233"
+    port:5672
+    user:"zx"
+    password:"zx123456"
+
+
+#   rabbitmq_reciever_vector
+#    {
+#        channel:413
+#        exchange_name:"command_ex"
+#
+#        binding_key:"count_command_signal_3_port"
+#        queue_name:"count_command_signal_3_queue"
+#        queue_passive:0
+#        queue_durable:1
+#        queue_exclusive:0
+#        queue_auto_delete:0
+#        consume_name:"count_command_signal_3_consume"
+#        consume_no_local:0
+#        consume_no_ack:0
+#        consume_exclusive:0
+#    }
+#    rabbitmq_reciever_vector
+#    {
+#        channel:424
+#        exchange_name:"command_ex"
+#
+#        binding_key:"post_command_4_port"
+#        queue_name:"post_command_4_queue"
+#        queue_passive:0
+#        queue_durable:1
+#        queue_exclusive:0
+#        queue_auto_delete:0
+#        consume_name:"post_command_4_consume"
+#        consume_no_local:0
+#        consume_no_ack:0
+#        consume_exclusive:0
+#    }
+
+
+
+
+
+    rabbitmq_reciever_vector
+    {
+       channel:605
+       exchange_name:"statu_ex"
+
+       binding_key:"measure_5_statu_port"
+       queue_name:"measure_5_statu_queue_for_dispatch"
+       queue_passive:0
+       queue_durable:0
+       queue_exclusive:0
+       queue_auto_delete:1
+       queue_meassage_ttl:1000
+       consume_name:"measure_5_statu_consume_for_dispatch"
+       consume_no_local:0
+       consume_no_ack:1
+       consume_exclusive:0
+    }
+
+    rabbitmq_reciever_vector
+    {
+        channel:606
+        exchange_name:"statu_ex"
+
+        binding_key:"measure_6_statu_port"
+        queue_name:"measure_6_statu_queue_for_dispatch"
+        queue_passive:0
+        queue_durable:0
+        queue_exclusive:0
+        queue_auto_delete:1
+       queue_meassage_ttl:1000
+        consume_name:"measure_6_statu_consume_for_dispatch"
+        consume_no_local:0
+        consume_no_ack:1
+        consume_exclusive:0
+    }
+
+    rabbitmq_reciever_vector
+    {
+        channel:705
+        exchange_name:"statu_ex"
+
+        binding_key:"in_mcpu_5_statu_port"
+        queue_name:"in_mcpu_5_statu_queue_for_dispatch"
+        queue_passive:0
+        queue_durable:0
+        queue_exclusive:0
+        queue_auto_delete:1
+       queue_meassage_ttl:1000
+        consume_name:"in_mcpu_5_statu_consume_for_dispatch"
+        consume_no_local:0
+        consume_no_ack:1
+        consume_exclusive:0
+    }
+
+    rabbitmq_reciever_vector
+    {
+        channel:706
+        exchange_name:"statu_ex"
+
+        binding_key:"in_mcpu_6_statu_port"
+        queue_name:"in_mcpu_6_statu_queue_for_dispatch"
+        queue_passive:0
+        queue_durable:0
+        queue_exclusive:0
+        queue_auto_delete:1
+       queue_meassage_ttl:1000
+        consume_name:"in_mcpu_6_statu_consume_for_dispatch"
+        consume_no_local:0
+        consume_no_ack:1
+        consume_exclusive:0
+    }
+
+    rabbitmq_reciever_vector
+    {
+        channel:805
+        exchange_name:"statu_ex"
+
+        binding_key:"out_mcpu_5_statu_port"
+        queue_name:"out_mcpu_5_statu_queue_for_dispatch"
+        queue_passive:0
+        queue_durable:0
+        queue_exclusive:0
+        queue_auto_delete:1
+       queue_meassage_ttl:1000
+        consume_name:"out_mcpu_5_statu_consume_for_dispatch"
+        consume_no_local:0
+        consume_no_ack:1
+        consume_exclusive:0
+    }
+
+    rabbitmq_reciever_vector
+    {
+        channel:806
+        exchange_name:"statu_ex"
+
+        binding_key:"out_mcpu_6_statu_port"
+        queue_name:"out_mcpu_6_statu_queue_for_dispatch"
+        queue_passive:0
+        queue_durable:0
+        queue_exclusive:0
+        queue_auto_delete:1
+       queue_meassage_ttl:1000
+        consume_name:"out_mcpu_6_statu_consume_for_dispatch"
+        consume_no_local:0
+        consume_no_ack:1
+        consume_exclusive:0
+    }
+
+
+
+
+
+
+    rabbitmq_sender_request_vector
+    {
+        channel:433
+        exchange_name:"command_ex"
+        routing_key:"request_command_port"
+        timeout_ms:0
+    }
+
+    rabbitmq_sender_request_vector
+    {
+        channel:443
+        exchange_name:"command_ex"
+        routing_key:"command_completed_port"
+        timeout_ms:0
+    }
+
+    rabbitmq_sender_status_vector
+    {
+        channel:453
+        exchange_name:"statu_ex"
+        routing_key:"dispatch_3_statu_port"
+        timeout_ms:10000
+    }
+
+}

+ 16 - 0
plc调度节点/setting/snap7_communication.prototxt

@@ -0,0 +1,16 @@
+
+snap7_communication_parameters
+{
+  #  ip_string:"192.168.0.1"
+ #   ip_string:"192.168.2.134"
+
+ #ip_string:"192.168.0.6"
+
+ #ip_string:"192.168.2.6"
+
+
+
+ #ip_string:"192.168.0.112"
+ ip_string:"192.168.0.1"
+}
+

+ 21 - 0
plc调度节点/setting/snap7_communication_a.prototxt

@@ -0,0 +1,21 @@
+
+snap7_communication_parameters
+{
+  #  ip_string:"192.168.0.1"
+ #   ip_string:"192.168.2.134"
+
+ #ip_string:"192.168.0.6"
+
+ #ip_string:"192.168.2.6"
+
+
+
+ #ip_string:"192.168.0.112"
+
+
+
+
+ #ip_string:"192.168.0.1"
+ ip_string:"192.168.0.81"
+}
+

+ 16 - 0
plc调度节点/setting/snap7_communication_b.prototxt

@@ -0,0 +1,16 @@
+
+snap7_communication_parameters
+{
+  #  ip_string:"192.168.0.1"
+ #   ip_string:"192.168.2.134"
+
+ #ip_string:"192.168.0.6"
+
+ #ip_string:"192.168.2.6"
+
+
+
+ #ip_string:"192.168.0.112"
+ ip_string:"192.168.0.161"
+}
+

+ 16 - 0
plc调度节点/setting/snap7_communication_c.prototxt

@@ -0,0 +1,16 @@
+
+snap7_communication_parameters
+{
+  #  ip_string:"192.168.0.1"
+ #   ip_string:"192.168.2.134"
+
+ #ip_string:"192.168.0.6"
+
+ #ip_string:"192.168.2.6"
+
+
+
+ #ip_string:"192.168.0.112"
+ ip_string:"192.168.0.1"
+}
+

+ 182 - 0
plc调度节点/snap7_communication/plc_data.cpp

@@ -0,0 +1,182 @@
+//
+// Created by zx on 2019/12/9.
+//
+
+#include "plc_data.h"
+#include <string.h>
+Plc_data *Plc_data::g_ins = 0;
+std::mutex Plc_data::g_lock;
+
+/**
+ * 获取单例句柄
+ * */
+Plc_data *Plc_data::get_instance(std::string ip)
+{
+    if (g_ins == 0)
+    {
+        std::lock_guard<std::mutex> lock(g_lock);
+        if (g_ins == 0)
+        {
+            if (ip != "")
+            {
+                g_ins = new Plc_data(ip);
+                LOG(INFO) << "plc data, handle created";
+            }
+            else
+            {
+                return 0;
+            }
+        }
+    }
+    return g_ins;
+}
+
+// void Plc_data::Release()
+// {
+//     if (g_ins)
+//     {
+//         g_ins->m_cond_exit.Notify(true);
+//         LOG(INFO) << "plc data, try to exit plc send thread";
+//         g_lock.lock();
+//         if (g_ins->p_send_thread)
+//         {
+//             LOG(INFO) << "plc data, try to join plc send thread";
+//             // LOG(INFO) << g_ins->p_send_thread->joinable();
+//             if (g_ins->p_send_thread->joinable())
+//                 g_ins->p_send_thread->join();
+//             LOG(INFO) << "plc data, try to delete plc send thread";
+//             delete g_ins->p_send_thread;
+//             g_ins->p_send_thread = 0;
+//             LOG(INFO) << "plc data, delete data send thread";
+//         }
+//         g_lock.unlock();
+
+//         LOG(INFO) << "plc data, start to exit plc handle";
+//         // if(g_instance->p_plc){
+//         //     LOG(INFO)<<"plc data, try to delete plc handle";
+//         //     delete g_instance->p_plc;
+//         //     g_instance->p_plc = 0;
+//         // }
+//         // LOG(INFO)<<"plc data, delete plc handle";
+//         LOG(INFO) << "plc data, delete instance";
+//         // delete g_ins;
+//         // g_ins = 0;
+//         LOG(INFO) << "plc data, instance deleted";
+//     }
+//     else
+//     {
+//         LOG(WARNING) << "plc data, cannot find the instance";
+//     }
+// }
+
+/**
+ * 更新区域状态
+ * */
+void Plc_data::update_data(int state_code, int border_status, int id)
+{
+//     LOG(INFO) << "plc data 更新数据 id: "<<id<<", code: "<<state_code;
+    if(id<0 || id>=MAX_REGIONS)
+        return ;
+    std::lock_guard<std::mutex> lock(g_lock);
+    m_data[2 * id] = state_code;
+    m_data[2 * id + 1] = border_status;
+}
+
+/**
+ * plc更新线程,将区域状态写入plc
+ * */
+void Plc_data::plc_update_thread(Plc_data *p)
+{
+    if (p == 0)
+    {
+        LOG(ERROR) << "plc update thread null pointer";
+        return;
+    }
+    while (!p->m_cond_exit.wait_for_millisecond(1))
+    {
+
+        // 判断plc状态
+        if (p->m_plc.getConnection() && p->mb_is_ready)
+        {
+
+
+            for (int i = 0; i < ELE_FENCE_COUNT; ++i)
+            {
+
+                g_lock.lock();
+                p->mb_is_ready = p->m_plc.WriteShorts(ELE_FENCE_DB_NUM,
+                                                      ELE_FENCE_BOUNDARY_START_ADDR + i * ELE_FENCE_OFFSET,
+                                                      2,
+                                                      p->m_data + (i * 2));
+                memcpy(p->m_last_data + (i * 2), p->m_data + (i * 2), 2 * sizeof(short));
+
+                g_lock.unlock();
+                usleep(10 * 1000);
+            }
+
+        }
+        else
+        {
+            // 重连plc
+            LOG(WARNING) << "find plc connection error, trying to reconnect.";
+            g_lock.lock();
+            p->m_plc.disconnect();
+            // LOG(WARNING) << "find plc connection error, diconnect first.";
+            if (p->m_ip_str != "")
+            {
+                p->mb_is_ready = p->m_plc.connect(p->m_ip_str);
+                // LOG(WARNING) << "find plc connection error, trying to connect";
+                if (p->mb_is_ready)
+                {
+                    LOG(INFO) << "successfully reconnect.";
+                }
+                else
+                {
+                    LOG(WARNING) << "failed to connect plc.";
+                }
+            }
+            g_lock.unlock();
+            usleep(p->m_update_interval_milli * 5 * 1000);
+        }
+        usleep(p->m_update_interval_milli * 1000);
+    }
+}
+
+/**
+ * 有参构造
+ * */
+Plc_data::Plc_data(std::string ip) : mp_update_thread(0),
+                                     m_ip_str(""),
+                                     mb_is_ready(0)
+{
+    m_ip_str = ip;
+    memset(m_data, 0, MAX_REGIONS*2 * sizeof(short));
+    memset(m_last_data, 0, MAX_REGIONS*2 * sizeof(short));
+    // p_plc = new S7PLC();
+    if (m_ip_str != "")
+    {
+        if (m_plc.connect(m_ip_str))
+        {
+            mb_is_ready = true;
+        }
+        else
+        {
+            LOG(ERROR) << "Plc_data instance, connect failed";
+        }
+    }
+    else
+    {
+        LOG(ERROR) << "Plc_data instance, empty ip string.";
+    }
+    m_cond_exit.notify_all(false);
+    mp_update_thread = new std::thread(plc_update_thread, this);
+    mp_update_thread->detach();
+}
+
+/**
+ * 获取plc连接状态
+ * */
+bool Plc_data::get_plc_status()
+{
+    return mb_is_ready;
+}

+ 75 - 0
plc调度节点/snap7_communication/plc_data.h

@@ -0,0 +1,75 @@
+//
+// Created by zx on 2019/12/9.
+//
+
+#ifndef PLC_DATA_H
+#define PLC_DATA_H
+#include <iostream>
+#include <string>
+#include <mutex>
+#include <atomic>
+#include "../tool/thread_condition.h"
+#include <thread>
+#include "../snap7_communication/s7_plc.h"
+#include "unistd.h"
+//#include "define.h"
+#include "glog/logging.h"
+
+#define MAX_REGIONS 6
+#define ELE_FENCE_BOUNDARY_START_ADDR 3
+#define ELE_FENCE_DB_NUM 95
+#define ELE_FENCE_OFFSET 7
+#define ELE_FENCE_COUNT 6
+
+#define CENTRAL_CONTROLLER_DB_NUM 41
+#define DOOR_STATUS_OFFSET 18
+
+
+class Plc_data
+{
+public:
+    // 获取plc通信类单例
+    static Plc_data *get_instance(std::string ip = "");
+    // static void Release();
+    // 更新区域状态数据
+    void update_data(int state_code, int border_status, int id);
+    // plc更新线程
+    static void plc_update_thread(Plc_data *p);
+    // 获取plc实时状态
+    bool get_plc_status();
+
+public:
+    std::atomic<bool> mb_is_ready; // 状态正常与否
+
+private:
+    static Plc_data *g_ins;   // 全局Plc_data实例
+    static std::mutex g_lock; // 全局Plc_data实例访问互斥锁
+
+    Thread_condition m_cond_exit;                // 系统关闭标志
+    std::thread *mp_update_thread;           // plc更新线程
+    S7PLC m_plc;                             // S7协议句柄
+    const int m_update_interval_milli = 100; // plc更新频率
+
+    // 有参构造函数
+    Plc_data(std::string ip);
+
+    // class CGarbo
+    // {
+    // public:
+    // 	~CGarbo() {
+    // 		if (g_ins)
+    // 		{
+    // 			delete g_ins;
+    // 			g_ins = 0;
+    // 		}
+    // 	}
+    // };
+    // static CGarbo Garbo;	//--->1
+
+protected:
+    short m_data[MAX_REGIONS*2];
+    short m_last_data[MAX_REGIONS*2];
+    std::string m_ip_str;
+};
+
+#endif //PLC_DATA_H

+ 85 - 0
plc调度节点/snap7_communication/s7_plc.cpp

@@ -0,0 +1,85 @@
+#include "s7_plc.h"
+
+S7PLC::S7PLC():bConnected_(false)
+{
+}
+S7PLC::~S7PLC()
+{
+    disconnect();
+}
+
+bool S7PLC::getConnection(){
+    return bConnected_;
+}
+
+bool S7PLC::connect(std::string ip)    
+{
+    std::lock_guard<std::mutex> lck (mutex_);
+    int ret=client_.ConnectTo(ip.c_str(),0,1);
+    bConnected_=(ret==0);
+    return bConnected_;
+}
+
+bool S7PLC::ReadShorts(int DBNumber,int start,int size,short* pdata)
+{
+    short* plc_data= (short*)malloc(size*sizeof(short));
+    bool ret=read_dbs(DBNumber,start*sizeof(short),size*sizeof(short),pdata);
+    if(ret)
+    {
+        reverse_byte(pdata,size*sizeof(short),plc_data);
+        for(int i=0;i<size;++i)
+            pdata[i]=plc_data[size-i-1];
+    }
+    free(plc_data);
+    return ret;
+
+}
+    bool S7PLC::WriteShorts(int DBNumber,int start,int size,short* pdata)
+    {
+        short* plc_data=(short*)malloc(size*sizeof(short));
+        memcpy(plc_data,pdata,size*sizeof(short));
+        for(int i=0;i<size;++i)
+            plc_data[i]=HTON(plc_data[i]);
+
+        bool ret=write_dbs(DBNumber,start*sizeof(short),size*sizeof(short),plc_data);
+        free(plc_data);
+        return ret;
+    }
+
+ bool S7PLC::read_dbs(int DBNumber,int start,int size,void* pdata)
+ {
+     std::lock_guard<std::mutex> lck (mutex_);
+     usleep(1000* 50);
+     if(bConnected_==false)
+        return false;
+     
+     int ret=client_.AsDBRead(DBNumber,start,size,pdata);
+
+     return ret == 0;
+ }
+ bool S7PLC::write_dbs(int DBNumber, int start, int size, void *pdata)
+ {
+    std::lock_guard<std::mutex> lck(mutex_);
+    usleep(1000*50);
+     if(bConnected_==false)
+        return false;
+     
+     int ret = client_.AsDBWrite(DBNumber, start, size, pdata);
+
+     return ret == 0;
+ }
+ void S7PLC::disconnect()
+ {
+     std::lock_guard<std::mutex> lck(mutex_);
+     client_.Disconnect();
+ }
+
+ void S7PLC::reverse_byte(void* pdata,int num_byte,void* out)
+ {
+     char* pin=(char*)pdata;
+     char* pout=(char*)out;
+     for(int i=0;i<num_byte;++i)
+     {
+         pout[i]=pin[num_byte-i-1];
+     }
+ }

+ 32 - 0
plc调度节点/snap7_communication/s7_plc.h

@@ -0,0 +1,32 @@
+#ifndef S7__PLC__H
+#define S7__PLC__H
+
+#include <s7_client.h>
+#include <mutex>
+#include <iostream>
+
+class S7PLC
+{
+public:
+#define HTON(T) ((T) << 8) | ((T) >> 8)
+protected:
+    bool        bConnected_;
+    std::mutex  mutex_;
+    TSnap7Client client_;
+public:
+    S7PLC();
+    ~S7PLC();
+
+    bool connect(std::string ip);
+    bool getConnection();
+    bool ReadShorts(int DBNumber,int start,int size,short* pdata);
+    bool WriteShorts(int DBNumber,int start,int size,short* pdata);
+    void disconnect();
+private:
+    bool read_dbs(int DBNumber,int start,int size,void* pdata);
+    bool write_dbs(int DBNumber,int start,int size,void* pdata);
+    void reverse_byte(void* pdata,int num_byte,void* out);
+
+};
+
+#endif // !S7__PLC__H

+ 236 - 0
plc调度节点/snap7_communication/snap7_buf.cpp

@@ -0,0 +1,236 @@
+
+
+
+#include "snap7_buf.h"
+#include <string>
+#include <string.h>
+
+Snap7_buf::Snap7_buf()
+{
+	m_id = 0;
+	m_start_index = 0;
+	m_size = 0;
+	mp_buf_obverse = nullptr;
+	mp_buf_reverse = nullptr;
+	m_communication_mode = NO_COMMUNICATION;
+
+}
+Snap7_buf::Snap7_buf(const Snap7_buf& other)
+{
+	m_id = other.m_id;
+	m_start_index = other.m_start_index;
+	m_communication_mode = other.m_communication_mode;
+
+	if ( other.m_size > 0 && other.mp_buf_obverse != nullptr && other.mp_buf_reverse != nullptr)
+	{
+		mp_buf_obverse = (void*)malloc(other.m_size);
+		memcpy(mp_buf_obverse, other.mp_buf_obverse, other.m_size);
+		mp_buf_reverse = (void*)malloc(other.m_size);
+		memcpy(mp_buf_reverse, other.mp_buf_reverse, other.m_size);
+		m_size = other.m_size;
+		m_variable_information_vector=other.m_variable_information_vector;
+	}
+}
+Snap7_buf& Snap7_buf::operator =(const Snap7_buf& other)
+{
+	m_id = other.m_id;
+	m_start_index = other.m_start_index;
+	m_communication_mode = other.m_communication_mode;
+
+	if ( other.m_size > 0 && other.mp_buf_obverse != nullptr && other.mp_buf_reverse != nullptr)
+	{
+		mp_buf_obverse = (void*)malloc(other.m_size);
+		memcpy(mp_buf_obverse, other.mp_buf_obverse, other.m_size);
+		mp_buf_reverse = (void*)malloc(other.m_size);
+		memcpy(mp_buf_reverse, other.mp_buf_reverse, other.m_size);
+		m_size = other.m_size;
+		m_variable_information_vector=other.m_variable_information_vector;
+	}
+	return *this;
+}
+Snap7_buf::~Snap7_buf()
+{
+	if ( mp_buf_obverse )
+	{
+		free(mp_buf_obverse);
+		mp_buf_obverse = NULL;
+	}
+	if ( mp_buf_reverse )
+	{
+		free(mp_buf_reverse);
+		mp_buf_reverse = NULL;
+	}
+}
+
+Snap7_buf::Snap7_buf(int id, int start_index, int size,
+					 std::vector<Snap7_buf::Variable_information>& variable_information_vector,Communication_mode communication_mode)
+{
+	m_id = id;
+	m_start_index = start_index;
+	m_communication_mode = communication_mode;
+
+	if ( size > 0)
+	{
+		mp_buf_obverse = (void*)malloc(size);
+		memset(mp_buf_obverse, 0, size);
+		mp_buf_reverse = (void*)malloc(size);
+		memset(mp_buf_reverse, 0, size);
+		m_size = size;
+		m_variable_information_vector=variable_information_vector;
+	}
+}
+Snap7_buf::Snap7_buf(int id, int start_index, int size, void* p_buf_obverse, void* p_buf_reverse,
+					 std::vector<Snap7_buf::Variable_information>& variable_information_vector, Communication_mode communication_mode)
+{
+	m_id = id;
+	m_start_index = start_index;
+	m_communication_mode = communication_mode;
+
+	if ( size > 0 && p_buf_obverse != nullptr && p_buf_reverse != nullptr)
+	{
+		mp_buf_obverse = (void*)malloc(size);
+		memcpy(mp_buf_obverse, p_buf_obverse, size);
+		mp_buf_reverse = (void*)malloc(size);
+		memcpy(mp_buf_reverse, p_buf_reverse, size);
+		m_size = size;
+		m_variable_information_vector=variable_information_vector;
+	}
+}
+void Snap7_buf::init(int id, int start_index, int size,
+		  std::vector<Snap7_buf::Variable_information>& variable_information_vector,Communication_mode communication_mode)
+{
+	m_id = id;
+	m_start_index = start_index;
+	m_communication_mode = communication_mode;
+
+	if ( mp_buf_obverse )
+	{
+		free(mp_buf_obverse);
+		mp_buf_obverse = NULL;
+	}
+	if ( mp_buf_reverse )
+	{
+		free(mp_buf_reverse);
+		mp_buf_reverse = NULL;
+	}
+
+	if ( size > 0)
+	{
+		mp_buf_obverse = (void*)malloc(size);
+		memset(mp_buf_obverse, 0, size);
+		mp_buf_reverse = (void*)malloc(size);
+		memset(mp_buf_reverse, 0, size);
+		m_size = size;
+		m_variable_information_vector=variable_information_vector;
+	}
+}
+
+void Snap7_buf::init(int id, int start_index, int size, void* p_buf_obverse, void* p_buf_reverse,
+		  std::vector<Snap7_buf::Variable_information>& variable_information_vector, Communication_mode communication_mode)
+{
+	m_id = id;
+	m_start_index = start_index;
+	m_communication_mode = communication_mode;
+
+	if ( mp_buf_obverse )
+	{
+		free(mp_buf_obverse);
+		mp_buf_obverse = NULL;
+	}
+	if ( mp_buf_reverse )
+	{
+		free(mp_buf_reverse);
+		mp_buf_reverse = NULL;
+	}
+
+	if ( size > 0 && p_buf_obverse != nullptr && p_buf_reverse != nullptr)
+	{
+		mp_buf_obverse = (void*)malloc(size);
+		memcpy(mp_buf_obverse, p_buf_obverse, size);
+		mp_buf_reverse = (void*)malloc(size);
+		memcpy(mp_buf_reverse, p_buf_reverse, size);
+		m_size = size;
+		m_variable_information_vector=variable_information_vector;
+	}
+}
+//正序数据 转为 倒序数据
+void Snap7_buf::obverse_to_reverse()
+{
+	char *p_in=(char*)mp_buf_obverse;
+	char *p_out=(char*)mp_buf_reverse;
+
+	for ( auto &iter:m_variable_information_vector)
+	{
+		for (int i = 0; i < iter.m_variable_count; ++i)
+		{
+			for (int j = 0; j < iter.m_variable_size; ++j)
+			{
+				p_out[iter.m_variable_index+iter.m_variable_size*i+j] = p_in[iter.m_variable_index+iter.m_variable_size*(i+1)-j-1];
+			}
+		}
+//		for (int i = 0; i < iter.m_variable_count; ++i)
+//		{
+//			for (int j = iter.m_variable_index*i; j < iter.m_variable_index*i+iter.m_variable_size ; ++j)
+//			{
+//				p_out[j] = p_in[iter.m_variable_index*i+iter.m_variable_size - j -1];
+//			}
+//		}
+	}
+}
+
+//倒序数据 转为 正序数据
+void Snap7_buf::reverse_to_obverse()
+{
+	char *p_in=(char*)mp_buf_reverse;
+	char *p_out=(char*)mp_buf_obverse;
+
+
+	for ( auto &iter:m_variable_information_vector)
+	{
+		for (int i = 0; i < iter.m_variable_count; ++i)
+		{
+			for (int j = 0; j < iter.m_variable_size; ++j)
+			{
+				p_out[iter.m_variable_index+iter.m_variable_size*i+j] = p_in[iter.m_variable_index+iter.m_variable_size*(i+1)-j-1];
+			}
+		}
+
+//		for (int i = 0; i < iter.m_variable_count; ++i)
+//		{
+//			for (int j = iter.m_variable_index*i; j < iter.m_variable_index*i+iter.m_variable_size ; ++j)
+//			{
+//				p_out[j] = p_in[iter.m_variable_index*i+iter.m_variable_size - j -1];
+//			}
+//		}
+	}
+}
+
+int Snap7_buf::get_id()
+{
+	return m_id;
+}
+int Snap7_buf::get_start_index()
+{
+	return m_start_index;
+}
+int Snap7_buf::get_size()
+{
+	return m_size;
+}
+void* Snap7_buf::get_buf_obverse()
+{
+	return mp_buf_obverse;
+}
+void* Snap7_buf::get_buf_reverse()
+{
+	return mp_buf_reverse;
+}
+
+Snap7_buf::Communication_mode Snap7_buf::get_communication_mode()
+{
+	return m_communication_mode;
+}
+void Snap7_buf::set_communication_mode(Communication_mode communication_mode)
+{
+	m_communication_mode = communication_mode;
+}

+ 85 - 0
plc调度节点/snap7_communication/snap7_buf.h

@@ -0,0 +1,85 @@
+
+
+
+#ifndef NNXX_TESTS_SNAP7_BUF_H
+#define NNXX_TESTS_SNAP7_BUF_H
+
+#include <string>
+#include <map>
+#include <vector>
+#include <iostream>
+
+//Snap7协议的数据结构
+class Snap7_buf
+{
+public:
+	//通信模式
+	enum Communication_mode
+	{
+	    NO_COMMUNICATION               		= 0,    //不通信
+	    ONCE_COMMUNICATION               	= 1,    //一次通信
+	    LOOP_COMMUNICATION					= 2,	//循环通信
+	};
+
+	//变量信息
+	struct Variable_information
+	{
+	    std::string		m_variable_name;		//变量名称
+	    std::string		m_variable_type;		//变量类型, 使用 typeid(a).name() 获取
+	    int 			m_variable_index;		//变量下标, 偏移量
+	    int 			m_variable_size;		//变量类型大小
+		int				m_variable_count;		//变量个数
+	};
+public:
+	Snap7_buf();
+	Snap7_buf(const Snap7_buf& other);
+	Snap7_buf& operator =(const Snap7_buf& other);
+	~Snap7_buf();
+public://API functions
+	Snap7_buf(int id, int start_index, int size,
+			  std::vector<Snap7_buf::Variable_information>& variable_information_vector,Communication_mode communication_mode = NO_COMMUNICATION);
+	Snap7_buf(int id, int start_index, int size, void* p_buf_obverse, void* p_buf_reverse,
+			  std::vector<Snap7_buf::Variable_information>& variable_information_vector, Communication_mode communication_mode = NO_COMMUNICATION);
+
+	void init(int id, int start_index, int size,
+			  std::vector<Snap7_buf::Variable_information>& variable_information_vector,Communication_mode communication_mode = NO_COMMUNICATION);
+	void init(int id, int start_index, int size, void* p_buf_obverse, void* p_buf_reverse,
+		 std::vector<Snap7_buf::Variable_information>& variable_information_vector, Communication_mode communication_mode = NO_COMMUNICATION);
+
+
+	//正序数据 转为 倒序数据
+	void obverse_to_reverse();
+	//倒序数据 转为 正序数据
+	void reverse_to_obverse();
+public://get or set member variable
+	int get_id();
+	int get_start_index();
+	int get_size();
+	void* get_buf_obverse();
+	void* get_buf_reverse();
+	Communication_mode get_communication_mode();
+	void set_communication_mode(Communication_mode communication_mode);
+protected://member functions
+
+public://member variable
+
+	int 		m_id;					//Snap7协议的数据块的编号
+	int 		m_start_index;			//Snap7协议的数据起始位下标
+	int			m_size;					//Snap7协议的数据字节大小
+	void*		mp_buf_obverse;			//Snap7协议的正序数据指针, 和数据结构体进行强转, 内存由本类管理
+	void*		mp_buf_reverse;			//Snap7协议的倒序数据指针, 用作s7通信, 内存由本类管理
+	//注:s7的通信的数据必须要倒序之后才能进行通信,
+
+//	std::map<std::string, Variable_information>			m_variable_information_map;
+	std::vector<Variable_information>		m_variable_information_vector;
+
+	Communication_mode 		m_communication_mode;	//Snap7协议的通信模式
+	//注:s7协议传输很慢, 防止相同的数据重复发送...
+
+
+private:
+
+};
+
+
+#endif //NNXX_TESTS_SNAP7_BUF_H

+ 686 - 0
plc调度节点/snap7_communication/snap7_communication.pb.cc

@@ -0,0 +1,686 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: snap7_communication.proto
+
+#include "snap7_communication.pb.h"
+
+#include <algorithm>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/port.h>
+#include <google/protobuf/stubs/once.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/wire_format_lite_inl.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/generated_message_reflection.h>
+#include <google/protobuf/reflection_ops.h>
+#include <google/protobuf/wire_format.h>
+// This is a temporary google only hack
+#ifdef GOOGLE_PROTOBUF_ENFORCE_UNIQUENESS
+#include "third_party/protobuf/version.h"
+#endif
+// @@protoc_insertion_point(includes)
+namespace Snap7_communication_proto {
+class Snap7_communication_parameterDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<Snap7_communication_parameter>
+      _instance;
+} _Snap7_communication_parameter_default_instance_;
+class Snap7_communication_parameter_allDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<Snap7_communication_parameter_all>
+      _instance;
+} _Snap7_communication_parameter_all_default_instance_;
+}  // namespace Snap7_communication_proto
+namespace protobuf_snap7_5fcommunication_2eproto {
+void InitDefaultsSnap7_communication_parameterImpl() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+#ifdef GOOGLE_PROTOBUF_ENFORCE_UNIQUENESS
+  ::google::protobuf::internal::InitProtobufDefaultsForceUnique();
+#else
+  ::google::protobuf::internal::InitProtobufDefaults();
+#endif  // GOOGLE_PROTOBUF_ENFORCE_UNIQUENESS
+  ::Snap7_communication_proto::Snap7_communication_parameter::_default_ip_string_.DefaultConstruct();
+  *::Snap7_communication_proto::Snap7_communication_parameter::_default_ip_string_.get_mutable() = ::std::string("192.168.0.1", 11);
+  ::google::protobuf::internal::OnShutdownDestroyString(
+      ::Snap7_communication_proto::Snap7_communication_parameter::_default_ip_string_.get_mutable());
+  {
+    void* ptr = &::Snap7_communication_proto::_Snap7_communication_parameter_default_instance_;
+    new (ptr) ::Snap7_communication_proto::Snap7_communication_parameter();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::Snap7_communication_proto::Snap7_communication_parameter::InitAsDefaultInstance();
+}
+
+void InitDefaultsSnap7_communication_parameter() {
+  static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
+  ::google::protobuf::GoogleOnceInit(&once, &InitDefaultsSnap7_communication_parameterImpl);
+}
+
+void InitDefaultsSnap7_communication_parameter_allImpl() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+#ifdef GOOGLE_PROTOBUF_ENFORCE_UNIQUENESS
+  ::google::protobuf::internal::InitProtobufDefaultsForceUnique();
+#else
+  ::google::protobuf::internal::InitProtobufDefaults();
+#endif  // GOOGLE_PROTOBUF_ENFORCE_UNIQUENESS
+  protobuf_snap7_5fcommunication_2eproto::InitDefaultsSnap7_communication_parameter();
+  {
+    void* ptr = &::Snap7_communication_proto::_Snap7_communication_parameter_all_default_instance_;
+    new (ptr) ::Snap7_communication_proto::Snap7_communication_parameter_all();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::Snap7_communication_proto::Snap7_communication_parameter_all::InitAsDefaultInstance();
+}
+
+void InitDefaultsSnap7_communication_parameter_all() {
+  static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
+  ::google::protobuf::GoogleOnceInit(&once, &InitDefaultsSnap7_communication_parameter_allImpl);
+}
+
+::google::protobuf::Metadata file_level_metadata[2];
+
+const ::google::protobuf::uint32 TableStruct::offsets[] GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
+  GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::Snap7_communication_proto::Snap7_communication_parameter, _has_bits_),
+  GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::Snap7_communication_proto::Snap7_communication_parameter, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::Snap7_communication_proto::Snap7_communication_parameter, ip_string_),
+  0,
+  GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::Snap7_communication_proto::Snap7_communication_parameter_all, _has_bits_),
+  GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::Snap7_communication_proto::Snap7_communication_parameter_all, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::Snap7_communication_proto::Snap7_communication_parameter_all, snap7_communication_parameters_),
+  0,
+};
+static const ::google::protobuf::internal::MigrationSchema schemas[] GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
+  { 0, 6, sizeof(::Snap7_communication_proto::Snap7_communication_parameter)},
+  { 7, 13, sizeof(::Snap7_communication_proto::Snap7_communication_parameter_all)},
+};
+
+static ::google::protobuf::Message const * const file_default_instances[] = {
+  reinterpret_cast<const ::google::protobuf::Message*>(&::Snap7_communication_proto::_Snap7_communication_parameter_default_instance_),
+  reinterpret_cast<const ::google::protobuf::Message*>(&::Snap7_communication_proto::_Snap7_communication_parameter_all_default_instance_),
+};
+
+void protobuf_AssignDescriptors() {
+  AddDescriptors();
+  ::google::protobuf::MessageFactory* factory = NULL;
+  AssignDescriptors(
+      "snap7_communication.proto", schemas, file_default_instances, TableStruct::offsets, factory,
+      file_level_metadata, NULL, NULL);
+}
+
+void protobuf_AssignDescriptorsOnce() {
+  static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
+  ::google::protobuf::GoogleOnceInit(&once, &protobuf_AssignDescriptors);
+}
+
+void protobuf_RegisterTypes(const ::std::string&) GOOGLE_PROTOBUF_ATTRIBUTE_COLD;
+void protobuf_RegisterTypes(const ::std::string&) {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::internal::RegisterAllTypes(file_level_metadata, 2);
+}
+
+void AddDescriptorsImpl() {
+  InitDefaults();
+  static const char descriptor[] GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
+      "\n\031snap7_communication.proto\022\031Snap7_commu"
+      "nication_proto\"\?\n\035Snap7_communication_pa"
+      "rameter\022\036\n\tip_string\030\001 \002(\t:\013192.168.0.1\""
+      "\205\001\n!Snap7_communication_parameter_all\022`\n"
+      "\036snap7_communication_parameters\030\001 \002(\01328."
+      "Snap7_communication_proto.Snap7_communic"
+      "ation_parameter"
+  };
+  ::google::protobuf::DescriptorPool::InternalAddGeneratedFile(
+      descriptor, 255);
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
+    "snap7_communication.proto", &protobuf_RegisterTypes);
+}
+
+void AddDescriptors() {
+  static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
+  ::google::protobuf::GoogleOnceInit(&once, &AddDescriptorsImpl);
+}
+// Force AddDescriptors() to be called at dynamic initialization time.
+struct StaticDescriptorInitializer {
+  StaticDescriptorInitializer() {
+    AddDescriptors();
+  }
+} static_descriptor_initializer;
+}  // namespace protobuf_snap7_5fcommunication_2eproto
+namespace Snap7_communication_proto {
+
+// ===================================================================
+
+void Snap7_communication_parameter::InitAsDefaultInstance() {
+}
+::google::protobuf::internal::ExplicitlyConstructed< ::std::string> Snap7_communication_parameter::_default_ip_string_;
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int Snap7_communication_parameter::kIpStringFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+Snap7_communication_parameter::Snap7_communication_parameter()
+  : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+  if (GOOGLE_PREDICT_TRUE(this != internal_default_instance())) {
+    ::protobuf_snap7_5fcommunication_2eproto::InitDefaultsSnap7_communication_parameter();
+  }
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:Snap7_communication_proto.Snap7_communication_parameter)
+}
+Snap7_communication_parameter::Snap7_communication_parameter(const Snap7_communication_parameter& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(NULL),
+      _has_bits_(from._has_bits_),
+      _cached_size_(0) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ip_string_.UnsafeSetDefault(&::Snap7_communication_proto::Snap7_communication_parameter::_default_ip_string_.get());
+  if (from.has_ip_string()) {
+    ip_string_.AssignWithDefault(&::Snap7_communication_proto::Snap7_communication_parameter::_default_ip_string_.get(), from.ip_string_);
+  }
+  // @@protoc_insertion_point(copy_constructor:Snap7_communication_proto.Snap7_communication_parameter)
+}
+
+void Snap7_communication_parameter::SharedCtor() {
+  _cached_size_ = 0;
+  ip_string_.UnsafeSetDefault(&::Snap7_communication_proto::Snap7_communication_parameter::_default_ip_string_.get());
+}
+
+Snap7_communication_parameter::~Snap7_communication_parameter() {
+  // @@protoc_insertion_point(destructor:Snap7_communication_proto.Snap7_communication_parameter)
+  SharedDtor();
+}
+
+void Snap7_communication_parameter::SharedDtor() {
+  ip_string_.DestroyNoArena(&::Snap7_communication_proto::Snap7_communication_parameter::_default_ip_string_.get());
+}
+
+void Snap7_communication_parameter::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* Snap7_communication_parameter::descriptor() {
+  ::protobuf_snap7_5fcommunication_2eproto::protobuf_AssignDescriptorsOnce();
+  return ::protobuf_snap7_5fcommunication_2eproto::file_level_metadata[kIndexInFileMessages].descriptor;
+}
+
+const Snap7_communication_parameter& Snap7_communication_parameter::default_instance() {
+  ::protobuf_snap7_5fcommunication_2eproto::InitDefaultsSnap7_communication_parameter();
+  return *internal_default_instance();
+}
+
+Snap7_communication_parameter* Snap7_communication_parameter::New(::google::protobuf::Arena* arena) const {
+  Snap7_communication_parameter* n = new Snap7_communication_parameter;
+  if (arena != NULL) {
+    arena->Own(n);
+  }
+  return n;
+}
+
+void Snap7_communication_parameter::Clear() {
+// @@protoc_insertion_point(message_clear_start:Snap7_communication_proto.Snap7_communication_parameter)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  cached_has_bits = _has_bits_[0];
+  if (cached_has_bits & 0x00000001u) {
+    GOOGLE_DCHECK(!ip_string_.IsDefault(&::Snap7_communication_proto::Snap7_communication_parameter::_default_ip_string_.get()));
+    (*ip_string_.UnsafeRawStringPointer())->assign(*&::Snap7_communication_proto::Snap7_communication_parameter::_default_ip_string_.get());
+  }
+  _has_bits_.Clear();
+  _internal_metadata_.Clear();
+}
+
+bool Snap7_communication_parameter::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:Snap7_communication_proto.Snap7_communication_parameter)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // required string ip_string = 1 [default = "192.168.0.1"];
+      case 1: {
+        if (static_cast< ::google::protobuf::uint8>(tag) ==
+            static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_ip_string()));
+          ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+            this->ip_string().data(), static_cast<int>(this->ip_string().length()),
+            ::google::protobuf::internal::WireFormat::PARSE,
+            "Snap7_communication_proto.Snap7_communication_parameter.ip_string");
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:Snap7_communication_proto.Snap7_communication_parameter)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:Snap7_communication_proto.Snap7_communication_parameter)
+  return false;
+#undef DO_
+}
+
+void Snap7_communication_parameter::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:Snap7_communication_proto.Snap7_communication_parameter)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  cached_has_bits = _has_bits_[0];
+  // required string ip_string = 1 [default = "192.168.0.1"];
+  if (cached_has_bits & 0x00000001u) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->ip_string().data(), static_cast<int>(this->ip_string().length()),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "Snap7_communication_proto.Snap7_communication_parameter.ip_string");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      1, this->ip_string(), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:Snap7_communication_proto.Snap7_communication_parameter)
+}
+
+::google::protobuf::uint8* Snap7_communication_parameter::InternalSerializeWithCachedSizesToArray(
+    bool deterministic, ::google::protobuf::uint8* target) const {
+  (void)deterministic; // Unused
+  // @@protoc_insertion_point(serialize_to_array_start:Snap7_communication_proto.Snap7_communication_parameter)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  cached_has_bits = _has_bits_[0];
+  // required string ip_string = 1 [default = "192.168.0.1"];
+  if (cached_has_bits & 0x00000001u) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->ip_string().data(), static_cast<int>(this->ip_string().length()),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "Snap7_communication_proto.Snap7_communication_parameter.ip_string");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        1, this->ip_string(), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:Snap7_communication_proto.Snap7_communication_parameter)
+  return target;
+}
+
+size_t Snap7_communication_parameter::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:Snap7_communication_proto.Snap7_communication_parameter)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  // required string ip_string = 1 [default = "192.168.0.1"];
+  if (has_ip_string()) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->ip_string());
+  }
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = cached_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void Snap7_communication_parameter::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:Snap7_communication_proto.Snap7_communication_parameter)
+  GOOGLE_DCHECK_NE(&from, this);
+  const Snap7_communication_parameter* source =
+      ::google::protobuf::internal::DynamicCastToGenerated<const Snap7_communication_parameter>(
+          &from);
+  if (source == NULL) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:Snap7_communication_proto.Snap7_communication_parameter)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:Snap7_communication_proto.Snap7_communication_parameter)
+    MergeFrom(*source);
+  }
+}
+
+void Snap7_communication_parameter::MergeFrom(const Snap7_communication_parameter& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:Snap7_communication_proto.Snap7_communication_parameter)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  if (from.has_ip_string()) {
+    set_has_ip_string();
+    ip_string_.AssignWithDefault(&::Snap7_communication_proto::Snap7_communication_parameter::_default_ip_string_.get(), from.ip_string_);
+  }
+}
+
+void Snap7_communication_parameter::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:Snap7_communication_proto.Snap7_communication_parameter)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void Snap7_communication_parameter::CopyFrom(const Snap7_communication_parameter& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:Snap7_communication_proto.Snap7_communication_parameter)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool Snap7_communication_parameter::IsInitialized() const {
+  if ((_has_bits_[0] & 0x00000001) != 0x00000001) return false;
+  return true;
+}
+
+void Snap7_communication_parameter::Swap(Snap7_communication_parameter* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void Snap7_communication_parameter::InternalSwap(Snap7_communication_parameter* other) {
+  using std::swap;
+  ip_string_.Swap(&other->ip_string_);
+  swap(_has_bits_[0], other->_has_bits_[0]);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata Snap7_communication_parameter::GetMetadata() const {
+  protobuf_snap7_5fcommunication_2eproto::protobuf_AssignDescriptorsOnce();
+  return ::protobuf_snap7_5fcommunication_2eproto::file_level_metadata[kIndexInFileMessages];
+}
+
+
+// ===================================================================
+
+void Snap7_communication_parameter_all::InitAsDefaultInstance() {
+  ::Snap7_communication_proto::_Snap7_communication_parameter_all_default_instance_._instance.get_mutable()->snap7_communication_parameters_ = const_cast< ::Snap7_communication_proto::Snap7_communication_parameter*>(
+      ::Snap7_communication_proto::Snap7_communication_parameter::internal_default_instance());
+}
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int Snap7_communication_parameter_all::kSnap7CommunicationParametersFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+Snap7_communication_parameter_all::Snap7_communication_parameter_all()
+  : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+  if (GOOGLE_PREDICT_TRUE(this != internal_default_instance())) {
+    ::protobuf_snap7_5fcommunication_2eproto::InitDefaultsSnap7_communication_parameter_all();
+  }
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:Snap7_communication_proto.Snap7_communication_parameter_all)
+}
+Snap7_communication_parameter_all::Snap7_communication_parameter_all(const Snap7_communication_parameter_all& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(NULL),
+      _has_bits_(from._has_bits_),
+      _cached_size_(0) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  if (from.has_snap7_communication_parameters()) {
+    snap7_communication_parameters_ = new ::Snap7_communication_proto::Snap7_communication_parameter(*from.snap7_communication_parameters_);
+  } else {
+    snap7_communication_parameters_ = NULL;
+  }
+  // @@protoc_insertion_point(copy_constructor:Snap7_communication_proto.Snap7_communication_parameter_all)
+}
+
+void Snap7_communication_parameter_all::SharedCtor() {
+  _cached_size_ = 0;
+  snap7_communication_parameters_ = NULL;
+}
+
+Snap7_communication_parameter_all::~Snap7_communication_parameter_all() {
+  // @@protoc_insertion_point(destructor:Snap7_communication_proto.Snap7_communication_parameter_all)
+  SharedDtor();
+}
+
+void Snap7_communication_parameter_all::SharedDtor() {
+  if (this != internal_default_instance()) delete snap7_communication_parameters_;
+}
+
+void Snap7_communication_parameter_all::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* Snap7_communication_parameter_all::descriptor() {
+  ::protobuf_snap7_5fcommunication_2eproto::protobuf_AssignDescriptorsOnce();
+  return ::protobuf_snap7_5fcommunication_2eproto::file_level_metadata[kIndexInFileMessages].descriptor;
+}
+
+const Snap7_communication_parameter_all& Snap7_communication_parameter_all::default_instance() {
+  ::protobuf_snap7_5fcommunication_2eproto::InitDefaultsSnap7_communication_parameter_all();
+  return *internal_default_instance();
+}
+
+Snap7_communication_parameter_all* Snap7_communication_parameter_all::New(::google::protobuf::Arena* arena) const {
+  Snap7_communication_parameter_all* n = new Snap7_communication_parameter_all;
+  if (arena != NULL) {
+    arena->Own(n);
+  }
+  return n;
+}
+
+void Snap7_communication_parameter_all::Clear() {
+// @@protoc_insertion_point(message_clear_start:Snap7_communication_proto.Snap7_communication_parameter_all)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  cached_has_bits = _has_bits_[0];
+  if (cached_has_bits & 0x00000001u) {
+    GOOGLE_DCHECK(snap7_communication_parameters_ != NULL);
+    snap7_communication_parameters_->Clear();
+  }
+  _has_bits_.Clear();
+  _internal_metadata_.Clear();
+}
+
+bool Snap7_communication_parameter_all::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:Snap7_communication_proto.Snap7_communication_parameter_all)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // required .Snap7_communication_proto.Snap7_communication_parameter snap7_communication_parameters = 1;
+      case 1: {
+        if (static_cast< ::google::protobuf::uint8>(tag) ==
+            static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+               input, mutable_snap7_communication_parameters()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:Snap7_communication_proto.Snap7_communication_parameter_all)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:Snap7_communication_proto.Snap7_communication_parameter_all)
+  return false;
+#undef DO_
+}
+
+void Snap7_communication_parameter_all::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:Snap7_communication_proto.Snap7_communication_parameter_all)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  cached_has_bits = _has_bits_[0];
+  // required .Snap7_communication_proto.Snap7_communication_parameter snap7_communication_parameters = 1;
+  if (cached_has_bits & 0x00000001u) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      1, *this->snap7_communication_parameters_, output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:Snap7_communication_proto.Snap7_communication_parameter_all)
+}
+
+::google::protobuf::uint8* Snap7_communication_parameter_all::InternalSerializeWithCachedSizesToArray(
+    bool deterministic, ::google::protobuf::uint8* target) const {
+  (void)deterministic; // Unused
+  // @@protoc_insertion_point(serialize_to_array_start:Snap7_communication_proto.Snap7_communication_parameter_all)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  cached_has_bits = _has_bits_[0];
+  // required .Snap7_communication_proto.Snap7_communication_parameter snap7_communication_parameters = 1;
+  if (cached_has_bits & 0x00000001u) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        1, *this->snap7_communication_parameters_, deterministic, target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:Snap7_communication_proto.Snap7_communication_parameter_all)
+  return target;
+}
+
+size_t Snap7_communication_parameter_all::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:Snap7_communication_proto.Snap7_communication_parameter_all)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  // required .Snap7_communication_proto.Snap7_communication_parameter snap7_communication_parameters = 1;
+  if (has_snap7_communication_parameters()) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::MessageSize(
+        *this->snap7_communication_parameters_);
+  }
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = cached_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void Snap7_communication_parameter_all::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:Snap7_communication_proto.Snap7_communication_parameter_all)
+  GOOGLE_DCHECK_NE(&from, this);
+  const Snap7_communication_parameter_all* source =
+      ::google::protobuf::internal::DynamicCastToGenerated<const Snap7_communication_parameter_all>(
+          &from);
+  if (source == NULL) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:Snap7_communication_proto.Snap7_communication_parameter_all)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:Snap7_communication_proto.Snap7_communication_parameter_all)
+    MergeFrom(*source);
+  }
+}
+
+void Snap7_communication_parameter_all::MergeFrom(const Snap7_communication_parameter_all& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:Snap7_communication_proto.Snap7_communication_parameter_all)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  if (from.has_snap7_communication_parameters()) {
+    mutable_snap7_communication_parameters()->::Snap7_communication_proto::Snap7_communication_parameter::MergeFrom(from.snap7_communication_parameters());
+  }
+}
+
+void Snap7_communication_parameter_all::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:Snap7_communication_proto.Snap7_communication_parameter_all)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void Snap7_communication_parameter_all::CopyFrom(const Snap7_communication_parameter_all& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:Snap7_communication_proto.Snap7_communication_parameter_all)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool Snap7_communication_parameter_all::IsInitialized() const {
+  if ((_has_bits_[0] & 0x00000001) != 0x00000001) return false;
+  if (has_snap7_communication_parameters()) {
+    if (!this->snap7_communication_parameters_->IsInitialized()) return false;
+  }
+  return true;
+}
+
+void Snap7_communication_parameter_all::Swap(Snap7_communication_parameter_all* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void Snap7_communication_parameter_all::InternalSwap(Snap7_communication_parameter_all* other) {
+  using std::swap;
+  swap(snap7_communication_parameters_, other->snap7_communication_parameters_);
+  swap(_has_bits_[0], other->_has_bits_[0]);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  swap(_cached_size_, other->_cached_size_);
+}
+
+::google::protobuf::Metadata Snap7_communication_parameter_all::GetMetadata() const {
+  protobuf_snap7_5fcommunication_2eproto::protobuf_AssignDescriptorsOnce();
+  return ::protobuf_snap7_5fcommunication_2eproto::file_level_metadata[kIndexInFileMessages];
+}
+
+
+// @@protoc_insertion_point(namespace_scope)
+}  // namespace Snap7_communication_proto
+
+// @@protoc_insertion_point(global_scope)

+ 439 - 0
plc调度节点/snap7_communication/snap7_communication.pb.h

@@ -0,0 +1,439 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: snap7_communication.proto
+
+#ifndef PROTOBUF_snap7_5fcommunication_2eproto__INCLUDED
+#define PROTOBUF_snap7_5fcommunication_2eproto__INCLUDED
+
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+
+#if GOOGLE_PROTOBUF_VERSION < 3005000
+#error This file was generated by a newer version of protoc which is
+#error incompatible with your Protocol Buffer headers.  Please update
+#error your headers.
+#endif
+#if 3005000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
+#error This file was generated by an older version of protoc which is
+#error incompatible with your Protocol Buffer headers.  Please
+#error regenerate this file with a newer version of protoc.
+#endif
+
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/arena.h>
+#include <google/protobuf/arenastring.h>
+#include <google/protobuf/generated_message_table_driven.h>
+#include <google/protobuf/generated_message_util.h>
+#include <google/protobuf/metadata.h>
+#include <google/protobuf/message.h>
+#include <google/protobuf/repeated_field.h>  // IWYU pragma: export
+#include <google/protobuf/extension_set.h>  // IWYU pragma: export
+#include <google/protobuf/unknown_field_set.h>
+// @@protoc_insertion_point(includes)
+
+namespace protobuf_snap7_5fcommunication_2eproto {
+// Internal implementation detail -- do not use these members.
+struct TableStruct {
+  static const ::google::protobuf::internal::ParseTableField entries[];
+  static const ::google::protobuf::internal::AuxillaryParseTableField aux[];
+  static const ::google::protobuf::internal::ParseTable schema[2];
+  static const ::google::protobuf::internal::FieldMetadata field_metadata[];
+  static const ::google::protobuf::internal::SerializationTable serialization_table[];
+  static const ::google::protobuf::uint32 offsets[];
+};
+void AddDescriptors();
+void InitDefaultsSnap7_communication_parameterImpl();
+void InitDefaultsSnap7_communication_parameter();
+void InitDefaultsSnap7_communication_parameter_allImpl();
+void InitDefaultsSnap7_communication_parameter_all();
+inline void InitDefaults() {
+  InitDefaultsSnap7_communication_parameter();
+  InitDefaultsSnap7_communication_parameter_all();
+}
+}  // namespace protobuf_snap7_5fcommunication_2eproto
+namespace Snap7_communication_proto {
+class Snap7_communication_parameter;
+class Snap7_communication_parameterDefaultTypeInternal;
+extern Snap7_communication_parameterDefaultTypeInternal _Snap7_communication_parameter_default_instance_;
+class Snap7_communication_parameter_all;
+class Snap7_communication_parameter_allDefaultTypeInternal;
+extern Snap7_communication_parameter_allDefaultTypeInternal _Snap7_communication_parameter_all_default_instance_;
+}  // namespace Snap7_communication_proto
+namespace Snap7_communication_proto {
+
+// ===================================================================
+
+class Snap7_communication_parameter : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:Snap7_communication_proto.Snap7_communication_parameter) */ {
+ public:
+  Snap7_communication_parameter();
+  virtual ~Snap7_communication_parameter();
+
+  Snap7_communication_parameter(const Snap7_communication_parameter& from);
+
+  inline Snap7_communication_parameter& operator=(const Snap7_communication_parameter& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  Snap7_communication_parameter(Snap7_communication_parameter&& from) noexcept
+    : Snap7_communication_parameter() {
+    *this = ::std::move(from);
+  }
+
+  inline Snap7_communication_parameter& operator=(Snap7_communication_parameter&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
+    return _internal_metadata_.unknown_fields();
+  }
+  inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
+    return _internal_metadata_.mutable_unknown_fields();
+  }
+
+  static const ::google::protobuf::Descriptor* descriptor();
+  static const Snap7_communication_parameter& default_instance();
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const Snap7_communication_parameter* internal_default_instance() {
+    return reinterpret_cast<const Snap7_communication_parameter*>(
+               &_Snap7_communication_parameter_default_instance_);
+  }
+  static PROTOBUF_CONSTEXPR int const kIndexInFileMessages =
+    0;
+
+  void Swap(Snap7_communication_parameter* other);
+  friend void swap(Snap7_communication_parameter& a, Snap7_communication_parameter& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline Snap7_communication_parameter* New() const PROTOBUF_FINAL { return New(NULL); }
+
+  Snap7_communication_parameter* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL;
+  void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL;
+  void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL;
+  void CopyFrom(const Snap7_communication_parameter& from);
+  void MergeFrom(const Snap7_communication_parameter& from);
+  void Clear() PROTOBUF_FINAL;
+  bool IsInitialized() const PROTOBUF_FINAL;
+
+  size_t ByteSizeLong() const PROTOBUF_FINAL;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) PROTOBUF_FINAL;
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const PROTOBUF_FINAL;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      bool deterministic, ::google::protobuf::uint8* target) const PROTOBUF_FINAL;
+  int GetCachedSize() const PROTOBUF_FINAL { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const PROTOBUF_FINAL;
+  void InternalSwap(Snap7_communication_parameter* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return NULL;
+  }
+  inline void* MaybeArenaPtr() const {
+    return NULL;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const PROTOBUF_FINAL;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // required string ip_string = 1 [default = "192.168.0.1"];
+  bool has_ip_string() const;
+  void clear_ip_string();
+  static const int kIpStringFieldNumber = 1;
+  const ::std::string& ip_string() const;
+  void set_ip_string(const ::std::string& value);
+  #if LANG_CXX11
+  void set_ip_string(::std::string&& value);
+  #endif
+  void set_ip_string(const char* value);
+  void set_ip_string(const char* value, size_t size);
+  ::std::string* mutable_ip_string();
+  ::std::string* release_ip_string();
+  void set_allocated_ip_string(::std::string* ip_string);
+
+  // @@protoc_insertion_point(class_scope:Snap7_communication_proto.Snap7_communication_parameter)
+ private:
+  void set_has_ip_string();
+  void clear_has_ip_string();
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::internal::HasBits<1> _has_bits_;
+  mutable int _cached_size_;
+  static ::google::protobuf::internal::ExplicitlyConstructed< ::std::string> _default_ip_string_;
+  ::google::protobuf::internal::ArenaStringPtr ip_string_;
+  friend struct ::protobuf_snap7_5fcommunication_2eproto::TableStruct;
+  friend void ::protobuf_snap7_5fcommunication_2eproto::InitDefaultsSnap7_communication_parameterImpl();
+};
+// -------------------------------------------------------------------
+
+class Snap7_communication_parameter_all : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:Snap7_communication_proto.Snap7_communication_parameter_all) */ {
+ public:
+  Snap7_communication_parameter_all();
+  virtual ~Snap7_communication_parameter_all();
+
+  Snap7_communication_parameter_all(const Snap7_communication_parameter_all& from);
+
+  inline Snap7_communication_parameter_all& operator=(const Snap7_communication_parameter_all& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  Snap7_communication_parameter_all(Snap7_communication_parameter_all&& from) noexcept
+    : Snap7_communication_parameter_all() {
+    *this = ::std::move(from);
+  }
+
+  inline Snap7_communication_parameter_all& operator=(Snap7_communication_parameter_all&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
+    return _internal_metadata_.unknown_fields();
+  }
+  inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
+    return _internal_metadata_.mutable_unknown_fields();
+  }
+
+  static const ::google::protobuf::Descriptor* descriptor();
+  static const Snap7_communication_parameter_all& default_instance();
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const Snap7_communication_parameter_all* internal_default_instance() {
+    return reinterpret_cast<const Snap7_communication_parameter_all*>(
+               &_Snap7_communication_parameter_all_default_instance_);
+  }
+  static PROTOBUF_CONSTEXPR int const kIndexInFileMessages =
+    1;
+
+  void Swap(Snap7_communication_parameter_all* other);
+  friend void swap(Snap7_communication_parameter_all& a, Snap7_communication_parameter_all& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline Snap7_communication_parameter_all* New() const PROTOBUF_FINAL { return New(NULL); }
+
+  Snap7_communication_parameter_all* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL;
+  void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL;
+  void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL;
+  void CopyFrom(const Snap7_communication_parameter_all& from);
+  void MergeFrom(const Snap7_communication_parameter_all& from);
+  void Clear() PROTOBUF_FINAL;
+  bool IsInitialized() const PROTOBUF_FINAL;
+
+  size_t ByteSizeLong() const PROTOBUF_FINAL;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) PROTOBUF_FINAL;
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const PROTOBUF_FINAL;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      bool deterministic, ::google::protobuf::uint8* target) const PROTOBUF_FINAL;
+  int GetCachedSize() const PROTOBUF_FINAL { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const PROTOBUF_FINAL;
+  void InternalSwap(Snap7_communication_parameter_all* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return NULL;
+  }
+  inline void* MaybeArenaPtr() const {
+    return NULL;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const PROTOBUF_FINAL;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // required .Snap7_communication_proto.Snap7_communication_parameter snap7_communication_parameters = 1;
+  bool has_snap7_communication_parameters() const;
+  void clear_snap7_communication_parameters();
+  static const int kSnap7CommunicationParametersFieldNumber = 1;
+  const ::Snap7_communication_proto::Snap7_communication_parameter& snap7_communication_parameters() const;
+  ::Snap7_communication_proto::Snap7_communication_parameter* release_snap7_communication_parameters();
+  ::Snap7_communication_proto::Snap7_communication_parameter* mutable_snap7_communication_parameters();
+  void set_allocated_snap7_communication_parameters(::Snap7_communication_proto::Snap7_communication_parameter* snap7_communication_parameters);
+
+  // @@protoc_insertion_point(class_scope:Snap7_communication_proto.Snap7_communication_parameter_all)
+ private:
+  void set_has_snap7_communication_parameters();
+  void clear_has_snap7_communication_parameters();
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::internal::HasBits<1> _has_bits_;
+  mutable int _cached_size_;
+  ::Snap7_communication_proto::Snap7_communication_parameter* snap7_communication_parameters_;
+  friend struct ::protobuf_snap7_5fcommunication_2eproto::TableStruct;
+  friend void ::protobuf_snap7_5fcommunication_2eproto::InitDefaultsSnap7_communication_parameter_allImpl();
+};
+// ===================================================================
+
+
+// ===================================================================
+
+#ifdef __GNUC__
+  #pragma GCC diagnostic push
+  #pragma GCC diagnostic ignored "-Wstrict-aliasing"
+#endif  // __GNUC__
+// Snap7_communication_parameter
+
+// required string ip_string = 1 [default = "192.168.0.1"];
+inline bool Snap7_communication_parameter::has_ip_string() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void Snap7_communication_parameter::set_has_ip_string() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void Snap7_communication_parameter::clear_has_ip_string() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+inline void Snap7_communication_parameter::clear_ip_string() {
+  ip_string_.ClearToDefaultNoArena(&::Snap7_communication_proto::Snap7_communication_parameter::_default_ip_string_.get());
+  clear_has_ip_string();
+}
+inline const ::std::string& Snap7_communication_parameter::ip_string() const {
+  // @@protoc_insertion_point(field_get:Snap7_communication_proto.Snap7_communication_parameter.ip_string)
+  return ip_string_.GetNoArena();
+}
+inline void Snap7_communication_parameter::set_ip_string(const ::std::string& value) {
+  set_has_ip_string();
+  ip_string_.SetNoArena(&::Snap7_communication_proto::Snap7_communication_parameter::_default_ip_string_.get(), value);
+  // @@protoc_insertion_point(field_set:Snap7_communication_proto.Snap7_communication_parameter.ip_string)
+}
+#if LANG_CXX11
+inline void Snap7_communication_parameter::set_ip_string(::std::string&& value) {
+  set_has_ip_string();
+  ip_string_.SetNoArena(
+    &::Snap7_communication_proto::Snap7_communication_parameter::_default_ip_string_.get(), ::std::move(value));
+  // @@protoc_insertion_point(field_set_rvalue:Snap7_communication_proto.Snap7_communication_parameter.ip_string)
+}
+#endif
+inline void Snap7_communication_parameter::set_ip_string(const char* value) {
+  GOOGLE_DCHECK(value != NULL);
+  set_has_ip_string();
+  ip_string_.SetNoArena(&::Snap7_communication_proto::Snap7_communication_parameter::_default_ip_string_.get(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:Snap7_communication_proto.Snap7_communication_parameter.ip_string)
+}
+inline void Snap7_communication_parameter::set_ip_string(const char* value, size_t size) {
+  set_has_ip_string();
+  ip_string_.SetNoArena(&::Snap7_communication_proto::Snap7_communication_parameter::_default_ip_string_.get(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:Snap7_communication_proto.Snap7_communication_parameter.ip_string)
+}
+inline ::std::string* Snap7_communication_parameter::mutable_ip_string() {
+  set_has_ip_string();
+  // @@protoc_insertion_point(field_mutable:Snap7_communication_proto.Snap7_communication_parameter.ip_string)
+  return ip_string_.MutableNoArena(&::Snap7_communication_proto::Snap7_communication_parameter::_default_ip_string_.get());
+}
+inline ::std::string* Snap7_communication_parameter::release_ip_string() {
+  // @@protoc_insertion_point(field_release:Snap7_communication_proto.Snap7_communication_parameter.ip_string)
+  clear_has_ip_string();
+  return ip_string_.ReleaseNoArena(&::Snap7_communication_proto::Snap7_communication_parameter::_default_ip_string_.get());
+}
+inline void Snap7_communication_parameter::set_allocated_ip_string(::std::string* ip_string) {
+  if (ip_string != NULL) {
+    set_has_ip_string();
+  } else {
+    clear_has_ip_string();
+  }
+  ip_string_.SetAllocatedNoArena(&::Snap7_communication_proto::Snap7_communication_parameter::_default_ip_string_.get(), ip_string);
+  // @@protoc_insertion_point(field_set_allocated:Snap7_communication_proto.Snap7_communication_parameter.ip_string)
+}
+
+// -------------------------------------------------------------------
+
+// Snap7_communication_parameter_all
+
+// required .Snap7_communication_proto.Snap7_communication_parameter snap7_communication_parameters = 1;
+inline bool Snap7_communication_parameter_all::has_snap7_communication_parameters() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void Snap7_communication_parameter_all::set_has_snap7_communication_parameters() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void Snap7_communication_parameter_all::clear_has_snap7_communication_parameters() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+inline void Snap7_communication_parameter_all::clear_snap7_communication_parameters() {
+  if (snap7_communication_parameters_ != NULL) snap7_communication_parameters_->Clear();
+  clear_has_snap7_communication_parameters();
+}
+inline const ::Snap7_communication_proto::Snap7_communication_parameter& Snap7_communication_parameter_all::snap7_communication_parameters() const {
+  const ::Snap7_communication_proto::Snap7_communication_parameter* p = snap7_communication_parameters_;
+  // @@protoc_insertion_point(field_get:Snap7_communication_proto.Snap7_communication_parameter_all.snap7_communication_parameters)
+  return p != NULL ? *p : *reinterpret_cast<const ::Snap7_communication_proto::Snap7_communication_parameter*>(
+      &::Snap7_communication_proto::_Snap7_communication_parameter_default_instance_);
+}
+inline ::Snap7_communication_proto::Snap7_communication_parameter* Snap7_communication_parameter_all::release_snap7_communication_parameters() {
+  // @@protoc_insertion_point(field_release:Snap7_communication_proto.Snap7_communication_parameter_all.snap7_communication_parameters)
+  clear_has_snap7_communication_parameters();
+  ::Snap7_communication_proto::Snap7_communication_parameter* temp = snap7_communication_parameters_;
+  snap7_communication_parameters_ = NULL;
+  return temp;
+}
+inline ::Snap7_communication_proto::Snap7_communication_parameter* Snap7_communication_parameter_all::mutable_snap7_communication_parameters() {
+  set_has_snap7_communication_parameters();
+  if (snap7_communication_parameters_ == NULL) {
+    snap7_communication_parameters_ = new ::Snap7_communication_proto::Snap7_communication_parameter;
+  }
+  // @@protoc_insertion_point(field_mutable:Snap7_communication_proto.Snap7_communication_parameter_all.snap7_communication_parameters)
+  return snap7_communication_parameters_;
+}
+inline void Snap7_communication_parameter_all::set_allocated_snap7_communication_parameters(::Snap7_communication_proto::Snap7_communication_parameter* snap7_communication_parameters) {
+  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
+  if (message_arena == NULL) {
+    delete snap7_communication_parameters_;
+  }
+  if (snap7_communication_parameters) {
+    ::google::protobuf::Arena* submessage_arena = NULL;
+    if (message_arena != submessage_arena) {
+      snap7_communication_parameters = ::google::protobuf::internal::GetOwnedMessage(
+          message_arena, snap7_communication_parameters, submessage_arena);
+    }
+    set_has_snap7_communication_parameters();
+  } else {
+    clear_has_snap7_communication_parameters();
+  }
+  snap7_communication_parameters_ = snap7_communication_parameters;
+  // @@protoc_insertion_point(field_set_allocated:Snap7_communication_proto.Snap7_communication_parameter_all.snap7_communication_parameters)
+}
+
+#ifdef __GNUC__
+  #pragma GCC diagnostic pop
+#endif  // __GNUC__
+// -------------------------------------------------------------------
+
+
+// @@protoc_insertion_point(namespace_scope)
+
+}  // namespace Snap7_communication_proto
+
+// @@protoc_insertion_point(global_scope)
+
+#endif  // PROTOBUF_snap7_5fcommunication_2eproto__INCLUDED

+ 12 - 0
plc调度节点/snap7_communication/snap7_communication.proto

@@ -0,0 +1,12 @@
+syntax = "proto2";
+package Snap7_communication_proto;
+
+message Snap7_communication_parameter
+{
+    required string ip_string = 1 [default="192.168.0.1"];
+}
+
+message Snap7_communication_parameter_all
+{
+    required Snap7_communication_parameter        snap7_communication_parameters=1;
+}

+ 384 - 0
plc调度节点/snap7_communication/snap7_communication_base.cpp

@@ -0,0 +1,384 @@
+//
+// Created by huli on 2020/9/25.
+//
+
+#include "snap7_communication_base.h"
+#include "../tool/proto_tool.h"
+
+Snap7_communication_base::Snap7_communication_base()
+{
+	m_communication_status = SNAP7_COMMUNICATION_UNKNOWN;
+	m_communication_delay_time_ms = SNAP7_COMMUNICATION_DELAY_TIME_MS;
+	mp_communication_thread = NULL;
+
+}
+
+Snap7_communication_base::~Snap7_communication_base()
+{
+	communication_uninit();
+}
+
+//初始化 通信 模块。如下三选一
+Error_manager Snap7_communication_base::communication_init()
+{
+	return  communication_init_from_protobuf(SNAP7_COMMUNICATION_PARAMETER_PATH);
+}
+//初始化 通信 模块。从文件读取
+Error_manager Snap7_communication_base::communication_init_from_protobuf(std::string prototxt_path)
+{
+	Snap7_communication_proto::Snap7_communication_parameter_all t_snap7_communication_parameter_all;
+	if(!  proto_tool::read_proto_param(prototxt_path,t_snap7_communication_parameter_all) )
+	{
+		return Error_manager(SNAP7_READ_PROTOBUF_ERROR,MINOR_ERROR,
+							 "Snap7_communication_base::communication_init_from_protobuf read_proto_param  failed");
+	}
+	return communication_init_from_protobuf(t_snap7_communication_parameter_all);
+}
+//初始化 通信 模块。从protobuf读取
+Error_manager Snap7_communication_base::communication_init_from_protobuf(Snap7_communication_proto::Snap7_communication_parameter_all& snap7_communication_parameter_all)
+{
+	LOG(INFO) << " ---Snap7_communication_base::communication_init() --- "<< this;
+	Error_manager t_error;
+//	snap7_communication_parameter_all.DebugString();
+
+	if ( snap7_communication_parameter_all.snap7_communication_parameters().has_ip_string() )
+	{
+		m_ip_string = snap7_communication_parameter_all.snap7_communication_parameters().ip_string();
+		t_error = communication_connect(m_ip_string);
+		if ( t_error != Error_code::SUCCESS )
+		{
+			//连接失败, 不要直接返回, 而是改为断连, 后面继续启动线程, (线程内部有重连功能)
+			m_communication_status = SNAP7_COMMUNICATION_DISCONNECT;
+		}
+		else
+		{
+			m_communication_status = SNAP7_COMMUNICATION_READY;
+		}
+	}
+
+#ifdef PLC_S7_COMMUNICATION
+	//启动通信, run thread
+	communication_run();
+#endif
+
+	return Error_code::SUCCESS;
+}
+
+
+//反初始化 通信 模块。
+Error_manager Snap7_communication_base::communication_uninit()
+{
+	//关闭线程并回收资源
+	if (mp_communication_thread)
+	{
+		m_communication_condition.kill_all();
+	}
+	if (mp_communication_thread)
+	{
+		mp_communication_thread->join();
+		delete mp_communication_thread;
+		mp_communication_thread = NULL;
+	}
+
+	//清空map
+	{
+		std::unique_lock<std::mutex> t_lock(m_receive_buf_lock);
+		m_receive_buf_map.clear();
+	}
+	{
+		std::unique_lock<std::mutex> t_lock(m_send_buf_lock);
+		m_send_buf_map.clear();
+	}
+
+	communication_disconnect();
+	m_communication_status = SNAP7_COMMUNICATION_UNKNOWN;
+
+	return Error_code::SUCCESS;
+}
+
+
+
+//唤醒s7通信线程
+Error_manager Snap7_communication_base::communication_start()
+{
+	m_communication_condition.notify_all(true);
+	return Error_code::SUCCESS;
+}
+//停止s7通信线程
+Error_manager Snap7_communication_base::communication_stop()
+{
+	m_communication_condition.notify_all(false);
+	return Error_code::SUCCESS;
+}
+
+
+
+Snap7_communication_base::Snap7_communication_statu Snap7_communication_base::get_status()
+{
+	return m_communication_status;
+}
+
+//修改通信延时, 单位ms
+Error_manager Snap7_communication_base::set_communication_delay_time_ms(int time)
+{
+	m_communication_delay_time_ms = time;
+	return Error_code::SUCCESS;
+}
+
+//通信连接
+Error_manager Snap7_communication_base::communication_connect(std::string ip_string)
+{
+	std::unique_lock<std::mutex> t_lock(m_communication_lock);
+	int result=m_snap7_client.ConnectTo(ip_string.c_str(),0,1);
+	std::this_thread::sleep_for(std::chrono::milliseconds(m_communication_delay_time_ms));
+	if (result==0)
+	{
+		return Error_code::SUCCESS;
+	}
+	else
+	{
+		return Error_manager(Error_code::SNAP7_CONNECT_ERROR, Error_level::MINOR_ERROR,
+							 " Snap7_communication_base::communication_connect error ");
+	}
+	return Error_code::SUCCESS;
+}
+//启动通信, run thread
+Error_manager Snap7_communication_base::communication_run()
+{
+	//启动4个线程。
+	//接受线程默认循环, 内部的nn_recv进行等待, 超时1ms
+	m_communication_condition.reset(false, false, false);
+	mp_communication_thread = new std::thread(&Snap7_communication_base::communication_thread, this);
+
+	return Error_code::SUCCESS;
+}
+//通信断连
+Error_manager Snap7_communication_base::communication_disconnect()
+{
+	std::unique_lock<std::mutex> t_lock(m_communication_lock);
+	int result=m_snap7_client.Disconnect();
+	std::this_thread::sleep_for(std::chrono::milliseconds(m_communication_delay_time_ms));
+	if (result==0)
+	{
+		return Error_code::SUCCESS;
+	}
+	else
+	{
+		return Error_manager(Error_code::SNAP7_DISCONNECT_ERROR, Error_level::MINOR_ERROR,
+							 " Snap7_communication_base::communication_disconnect error ");
+	}
+	return Error_code::SUCCESS;
+}
+//mp_communication_thread线程的执行函数, 负责进行s7的通信
+void Snap7_communication_base::communication_thread()
+{
+	LOG(INFO) << " ---Snap7_communication_base::communication_thread()--- "<< this;
+Error_manager t_error;
+	while (m_communication_condition.is_alive())
+	{
+		m_communication_condition.wait_for_millisecond(1);
+
+		//s7的通信时间较长, 所以将发送和接受分开
+		//发送多个时, 必须加锁后一起发送, 不允许分段写入, 防止数据错误
+		if ( m_communication_condition.is_alive() )
+		{
+			std::this_thread::sleep_for(std::chrono::milliseconds(m_communication_delay_time_ms));
+			std::this_thread::yield();
+
+			switch ( m_communication_status )
+			{
+			    case SNAP7_COMMUNICATION_READY:
+				case SNAP7_COMMUNICATION_RECEIVE:
+			    {
+					{
+						std::unique_lock<std::mutex> t_lock(m_receive_buf_lock);
+						auto iter = m_receive_buf_map.begin();
+						for (; iter != m_receive_buf_map.end(); ++iter)
+						{
+							//接受数据, 读取DB块,
+							t_error = read_data_buf(iter->second);
+							if (t_error == Error_code::SNAP7_READ_ERROR)
+							{
+								m_communication_status = SNAP7_COMMUNICATION_DISCONNECT;
+								std::cout << " huli test :::: " << " t_error = " << t_error << std::endl;
+								break;
+							}
+						}
+						if ( iter != m_receive_buf_map.end() )
+						{
+							break;
+						}
+					}
+					//注:数据更新放在锁的外面, 防止重复加锁....
+					updata_receive_buf();
+					m_communication_status = SNAP7_COMMUNICATION_SEND;
+			        break;
+			    }
+			    case SNAP7_COMMUNICATION_SEND:
+			    {
+					//注:数据更新放在锁的外面, 防止重复加锁....
+					updata_send_buf();
+					{
+						std::unique_lock<std::mutex> t_lock(m_send_buf_lock);
+						auto iter = m_send_buf_map.begin();
+						for (; iter != m_send_buf_map.end(); ++iter)
+						{
+							//发送数据, 写入DB块,
+							t_error = write_data_buf(iter->second);
+							if (t_error == Error_code::SNAP7_WRITE_ERROR)
+							{
+								m_communication_status = SNAP7_COMMUNICATION_DISCONNECT;
+								std::cout << " huli test :::: " << " t_error = " << t_error << std::endl;
+								break;
+							}
+						}
+						if ( iter != m_send_buf_map.end() )
+						{
+							break;
+						}
+					}
+					m_communication_status = SNAP7_COMMUNICATION_RECEIVE;
+			        break;
+			    }
+				case SNAP7_COMMUNICATION_DISCONNECT:
+				{
+					//重连
+					LOG(INFO) << "find plc connection error, trying to reconnect.";
+					communication_disconnect();
+					std::this_thread::sleep_for(std::chrono::milliseconds(m_communication_delay_time_ms));
+					t_error = communication_connect(m_ip_string);
+					if ( t_error != Error_code::SUCCESS )
+					{
+						//连接失败, 不要直接返回, 而是改为断连, 后面继续启动线程, (线程内部有重连功能)
+						m_communication_status = SNAP7_COMMUNICATION_DISCONNECT;
+					}
+					else
+					{
+						m_communication_status = SNAP7_COMMUNICATION_READY;
+					}
+					std::this_thread::sleep_for(std::chrono::milliseconds(m_communication_delay_time_ms));
+
+					break;
+				}
+			    default:
+			    {
+
+			        break;
+			    }
+			}
+		}
+	}
+
+	LOG(INFO) << " Communication_socket_base::send_data_thread end "<< this;
+	return;
+}
+
+//接受数据, 读取DB块,
+Error_manager Snap7_communication_base::read_data_buf(Snap7_buf& snap7_buf)
+{
+	Error_manager t_error;
+	if ( snap7_buf.m_communication_mode != Snap7_buf::NO_COMMUNICATION)
+	{
+		if ( snap7_buf.m_communication_mode == Snap7_buf::ONCE_COMMUNICATION )
+		{
+			snap7_buf.m_communication_mode = Snap7_buf::NO_COMMUNICATION;
+		}
+
+
+
+
+		std::unique_lock<std::mutex> lck(m_communication_lock);
+		int result = m_snap7_client.AsDBRead(snap7_buf.m_id, snap7_buf.m_start_index, snap7_buf.m_size, snap7_buf.mp_buf_reverse);
+
+//		std::this_thread::sleep_for(std::chrono::milliseconds(10));
+		if ( result == 0 )
+		{
+			result = m_snap7_client.WaitAsCompletion(100);
+//			if ( result !=0 )
+//			{
+//				return Error_manager(Error_code::SNAP7_READ_ERROR, Error_level::MINOR_ERROR,
+//									 " Snap7_communication_base::read_data_buf error ");
+//			}
+			//倒序数据 转为 正序数据
+			snap7_buf.reverse_to_obverse();
+		}
+		else
+		{
+			std::cout << " huli test :::: " << " result = " << result << std::endl;
+			return Error_manager(Error_code::SNAP7_READ_ERROR, Error_level::MINOR_ERROR,
+								 " Snap7_communication_base::read_data_buf error ");
+		}
+	}
+
+	return Error_code::SUCCESS;
+}
+//发送数据, 写入DB块,
+Error_manager Snap7_communication_base::write_data_buf(Snap7_buf& snap7_buf)
+{
+	Error_manager t_error;
+	if ( snap7_buf.m_communication_mode != Snap7_buf::NO_COMMUNICATION)
+	{
+		if ( snap7_buf.m_communication_mode == Snap7_buf::ONCE_COMMUNICATION )
+		{
+			snap7_buf.m_communication_mode = Snap7_buf::NO_COMMUNICATION;
+		}
+
+		//正序数据 转为 倒序数据
+		snap7_buf.obverse_to_reverse();
+
+		std::unique_lock<std::mutex> lck(m_communication_lock);
+		int result = m_snap7_client.AsDBWrite(snap7_buf.m_id, snap7_buf.m_start_index, snap7_buf.m_size,
+											  snap7_buf.mp_buf_reverse);
+
+//		std::this_thread::sleep_for(std::chrono::milliseconds(10));
+		if ( result == 0 )
+		{
+			result = m_snap7_client.WaitAsCompletion(100);
+//			if ( result !=0 )
+//			{
+//				return Error_manager(Error_code::SNAP7_WRITE_ERROR, Error_level::MINOR_ERROR,
+//									 " Snap7_communication_base::write_data_buf error ");
+//			}
+		}
+		else
+		{
+			return Error_manager(Error_code::SNAP7_WRITE_ERROR, Error_level::MINOR_ERROR,
+								 " Snap7_communication_base::write_data_buf error ");
+		}
+	}
+	return Error_code::SUCCESS;
+}
+
+//数据颠倒
+Error_manager Snap7_communication_base::reverse_byte(void* p_buf_in, void* p_buf_out, int size)
+{
+	if ( p_buf_in == NULL || p_buf_out == NULL )
+	{
+	    return Error_manager(Error_code::POINTER_IS_NULL, Error_level::MINOR_ERROR,
+	    					"  POINTER IS NULL ");
+	}
+	char* tp_in=(char*)p_buf_in;
+	char* tp_out=(char*)p_buf_out;
+//	for(int i=0;i<size;++i)
+//	{
+//		tp_out[i]=tp_in[size-i-1];
+//	}
+	for(int i=0;i<size;++i)
+	{
+		tp_out[i]=tp_in[i];
+	}
+	return Error_code::SUCCESS;
+}
+
+//更新数据
+Error_manager Snap7_communication_base::updata_receive_buf()
+{
+	return Error_code::SUCCESS;
+}
+Error_manager Snap7_communication_base::updata_send_buf()
+{
+	return Error_code::SUCCESS;
+}
+
+
+

+ 112 - 0
plc调度节点/snap7_communication/snap7_communication_base.h

@@ -0,0 +1,112 @@
+//
+// Created by huli on 2020/9/25.
+//
+
+#ifndef NNXX_TESTS_SNAP7_E_BASE_H
+#define NNXX_TESTS_SNAP7_E_BASE_H
+
+#include <s7_client.h>
+#include <mutex>
+#include <map>
+#include <glog/logging.h>
+
+#include "../error_code/error_code.h"
+#include "../tool/thread_condition.h"
+#include "../snap7_communication/snap7_buf.h"
+#include "../snap7_communication/s7_plc.h"
+#include "../snap7_communication/snap7_communication.pb.h"
+
+class Snap7_communication_base
+{
+public:
+	//snap7的通信延时, 默认50ms
+#define SNAP7_COMMUNICATION_DELAY_TIME_MS 	10
+//snap7的通信参数路径
+#define SNAP7_COMMUNICATION_PARAMETER_PATH	"../setting/snap7_communication.prototxt"
+	//通信状态
+	enum Snap7_communication_statu
+	{
+		SNAP7_COMMUNICATION_UNKNOWN		=0,	        //通信状态 未知
+		SNAP7_COMMUNICATION_READY			=1,			//通信状态 正常
+
+		SNAP7_COMMUNICATION_RECEIVE		=2, 		//接受
+		SNAP7_COMMUNICATION_SEND			=3, 		//发送
+		SNAP7_COMMUNICATION_DISCONNECT	=4, 		//断连
+
+		SNAP7_COMMUNICATION_FAULT			=10,         //通信状态 错误
+	};
+public:
+	Snap7_communication_base();
+	Snap7_communication_base(const Snap7_communication_base& other)= default;
+	Snap7_communication_base& operator =(const Snap7_communication_base& other)= default;
+	~Snap7_communication_base();
+public://API functions
+	//初始化 通信 模块。如下三选一
+	virtual Error_manager communication_init();
+	//初始化 通信 模块。从文件读取
+	virtual Error_manager communication_init_from_protobuf(std::string prototxt_path);
+	//初始化 通信 模块。从protobuf读取
+	virtual Error_manager communication_init_from_protobuf(Snap7_communication_proto::Snap7_communication_parameter_all& snap7_communication_parameter_all);
+	//反初始化 通信 模块。
+	virtual Error_manager communication_uninit();
+
+	//唤醒s7通信线程
+	virtual Error_manager communication_start();
+	//停止s7通信线程
+	virtual Error_manager communication_stop();
+
+public://get or set member variable
+	Snap7_communication_statu get_status();
+
+	//修改通信延时, 单位ms
+	Error_manager set_communication_delay_time_ms(int time);
+
+protected://member functions
+	//通信连接
+	Error_manager communication_connect(std::string ip_string);
+	//启动通信, run thread
+	Error_manager communication_run();
+	//通信断连
+	Error_manager communication_disconnect();
+	//mp_communication_thread线程的执行函数, 负责进行s7的通信
+	void communication_thread();
+
+	//接受数据, 读取DB块,
+	Error_manager read_data_buf(Snap7_buf& snap7_buf);
+	//发送数据, 写入DB块,
+	Error_manager write_data_buf(Snap7_buf& snap7_buf);
+	//数据颠倒
+	Error_manager reverse_byte(void* p_buf_in, void* p_buf_out, int size);
+
+	//更新数据
+	virtual Error_manager updata_receive_buf();
+	virtual Error_manager updata_send_buf();
+protected://member variable
+public:
+	//状态
+	Snap7_communication_statu				m_communication_status;	//通信状态
+	std::string						m_ip_string;			//通信ip
+
+	//通信模块
+	std::mutex  					m_communication_lock;	//通信锁
+	TSnap7Client 					m_snap7_client;			//通信的客户端
+	int 							m_communication_delay_time_ms;//通信延时, 单位ms
+	//注:s7协议通信很不稳定, 在每次使用 TSnap7Client 之后, 都需要加延时
+
+	//数据
+	std::mutex  					m_receive_buf_lock;		//接受的锁
+	std::map<int, Snap7_buf>		m_receive_buf_map; 		//接受的map容器
+	std::mutex  					m_send_buf_lock;		//发送的锁
+	std::map<int, Snap7_buf>		m_send_buf_map; 		//发送的map容器
+
+	//线程, snap7的通信核心就是对 发送和接受内存的 周期性读写, 所以使用一个线程即可.
+	std::thread*					mp_communication_thread;    		//通信的线程指针
+	Thread_condition				m_communication_condition;			//通信的条件变量
+
+
+private:
+
+};
+
+
+#endif //NNXX_TESTS_SNAP7_E_BASE_H

+ 112 - 0
plc调度节点/system/system_communication.cpp

@@ -0,0 +1,112 @@
+//
+// Created by huli on 2020/6/28.
+//
+
+#include "system_communication.h"
+//#include "../laser/laser_manager.h"
+//#include "../locate/locate_manager.h"
+#include "../system/system_executor.h"
+
+System_communication::System_communication()
+{
+
+}
+
+System_communication::~System_communication()
+{
+
+}
+
+//初始化 通信 模块。如下三选一
+Error_manager System_communication::communication_init()
+{
+	return Rabbitmq_base::rabbitmq_init();
+}
+
+//初始化 通信 模块。如下三选一
+Error_manager System_communication::communication_init(int dispatch_id)
+{
+//	return Rabbitmq_base::rabbitmq_init();
+	switch ( dispatch_id )
+	{
+		case 0:
+		{
+			return Rabbitmq_base::rabbitmq_init_from_protobuf(RABBITMQ_PARAMETER_PATH_A);
+			break;
+		}
+		case 1:
+		{
+			return Rabbitmq_base::rabbitmq_init_from_protobuf(RABBITMQ_PARAMETER_PATH_B);
+			break;
+		}
+		case 2:
+		{
+			return Rabbitmq_base::rabbitmq_init_from_protobuf(RABBITMQ_PARAMETER_PATH_C);
+			break;
+		}
+		default:
+		{
+			return Error_manager(Error_code::COMMUNICATION_READ_PROTOBUF_ERROR, Error_level::MINOR_ERROR,
+								 " System_communication::communication_init dispatch_id error ");
+			break;
+		}
+	}
+	return Error_code::SUCCESS;
+}
+
+//检查消息是否有效, 主要检查消息类型和接受者, 判断这条消息是不是给我的.
+Error_manager System_communication::check_msg(Rabbitmq_message*  p_msg)
+{
+	return System_executor::get_instance_references().check_msg(p_msg);
+}
+
+//检查执行者的状态, 判断能否处理这条消息, 需要子类重载
+Error_manager System_communication::check_executer(Rabbitmq_message*  p_msg)
+{
+	return System_executor::get_instance_references().check_executer(p_msg);
+	/*
+	//检查对应模块的状态, 判断是否可以处理这条消息
+	//同时也要判断是否超时, 超时返回 COMMUNICATION_ANALYSIS_TIME_OUT
+	//如果处理器正在忙别的, 那么返回 COMMUNICATION_EXCUTER_IS_BUSY
+//	std::cout << "Communication_socket_base::check_msg  p_buf =  " << p_msg->get_message_buf() << std::endl;
+//	std::cout << "Communication_socket_base::check_msg   size =  " << p_msg->get_message_buf().size() << std::endl;
+
+	Error_manager t_error;
+	if ( p_msg->is_over_time() )
+	{
+		std::cout << "COMMUNICATION_ANALYSIS_TIME_OUT , " << std::endl;
+		//超时:接收方不做处理,发送方会进行超时处理
+		return Error_code::COMMUNICATION_ANALYSIS_TIME_OUT;
+	}
+	else
+	{
+		return System_executor::get_instance_references().check_executer(p_msg);
+	}
+	return Error_code::SUCCESS;
+	 */
+}
+
+//处理消息, 需要子类重载
+Error_manager System_communication::execute_msg(Rabbitmq_message* p_msg)
+{
+	return System_executor::get_instance_references().execute_msg(p_msg);
+}
+
+//定时封装发送消息, 一般为心跳和状态信息, 需要子类重载
+Error_manager System_communication::auto_encapsulate_status()
+{
+	Error_manager t_error;
+
+	return System_executor::get_instance_references().encapsulate_send_dispatch_manager_status();
+
+	return Error_code::SUCCESS;
+}
+
+
+
+
+
+
+
+
+

+ 55 - 0
plc调度节点/system/system_communication.h

@@ -0,0 +1,55 @@
+//
+// Created by huli on 2020/6/28.
+//
+
+#ifndef NNXX_TESTS_SYSTEM_COMMUNICATION_H
+#define NNXX_TESTS_SYSTEM_COMMUNICATION_H
+
+#include "../tool/singleton.h"
+//#include "../communication/communication_socket_base.h"
+#include "../rabbitmq/rabbitmq_base.h"
+
+#define RABBITMQ_PARAMETER_PATH_A "../setting/rabbitmq_a.prototxt"
+#define RABBITMQ_PARAMETER_PATH_B "../setting/rabbitmq_b.prototxt"
+#define RABBITMQ_PARAMETER_PATH_C "../setting/rabbitmq_c.prototxt"
+
+
+class System_communication:public Singleton<System_communication>, public Rabbitmq_base
+{
+
+// 子类必须把父类设定为友元函数,这样父类才能使用子类的私有构造函数。
+   friend class Singleton<System_communication>;
+private:
+ // 父类的构造函数必须保护,子类的构造函数必须私有。
+   System_communication();
+public:
+    //必须关闭拷贝构造和赋值构造,只能通过 get_instance 函数来进行操作唯一的实例。
+    System_communication(const System_communication& other) = delete;
+    System_communication& operator =(const System_communication& other) = delete;
+    ~System_communication();
+public://API functions
+	//初始化 通信 模块。如下三选一
+	virtual Error_manager communication_init();
+	virtual Error_manager communication_init(int dispatch_id);
+	//检查消息是否有效, 主要检查消息类型和接受者, 判断这条消息是不是给我的.
+	virtual Error_manager check_msg(Rabbitmq_message* p_msg);
+	//检查执行者的状态, 判断能否处理这条消息, 需要子类重载
+	virtual Error_manager check_executer(Rabbitmq_message* p_msg);
+	//处理消息, 需要子类重载
+	virtual Error_manager execute_msg(Rabbitmq_message* p_msg);
+
+	//定时封装发送消息, 一般为心跳和状态信息, 需要子类重载
+	virtual Error_manager auto_encapsulate_status();
+
+public://get or set member variable
+
+    
+protected://member variable 
+
+    
+private:
+    
+};
+
+
+#endif //NNXX_TESTS_SYSTEM_COMMUNICATION_H

+ 645 - 0
plc调度节点/system/system_executor.cpp

@@ -0,0 +1,645 @@
+//
+// Created by huli on 2020/7/2.
+//
+
+#include "system_executor.h"
+
+
+System_executor::System_executor()
+{
+
+}
+
+System_executor::~System_executor()
+{
+	system_executor_uninit();
+}
+
+//初始化
+Error_manager System_executor::system_executor_init(int threads_size)
+{
+	m_thread_pool.thread_pool_init(threads_size);
+	m_system_executor_status = SYSTEM_EXECUTOR_READY;
+	return Error_code::SUCCESS;
+}
+
+//反初始化
+Error_manager System_executor::system_executor_uninit()
+{
+	m_thread_pool.thread_pool_uninit();
+	m_system_executor_status = SYSTEM_EXECUTOR_UNKNOW;
+	return Error_code::SUCCESS;
+}
+
+//检查消息是否有效, 主要检查消息类型和接受者, 判断这条消息是不是给我的.
+Error_manager System_executor::check_msg(Rabbitmq_message* p_msg)
+{
+	return Error_code::SUCCESS;
+	/*
+	if ( p_msg == NULL )
+	{
+		return Error_manager(Error_code::POINTER_IS_NULL, Error_level::MINOR_ERROR,
+							 "  POINTER IS NULL ");
+	}
+	
+	//检查接受人
+	if ( p_msg->get_receiver() == Communication_message::Communicator::eDispatch_mamager )
+	{
+		//检查消息类型
+		switch ( p_msg->get_message_type() )
+		{
+			case Communication_message::Message_type::eDispatch_request_msg:
+			{
+				message::Dispatch_request_msg t_dispatch_request_msg;
+				//针对消息类型, 对消息进行二次解析
+				if (t_dispatch_request_msg.ParseFromString(p_msg->get_message_buf()))
+				{
+					if ( t_dispatch_request_msg.dispatch_motion_direction() == message::Dispatch_motion_direction::E_STORE_CAR )
+					{
+						if ( t_dispatch_request_msg.id_struct().has_terminal_id() &&
+							 t_dispatch_request_msg.mutable_id_struct()->terminal_id() == Dispatch_manager::get_instance_references().get_dispatch_manager_id()*2 ||
+							 t_dispatch_request_msg.mutable_id_struct()->terminal_id() == Dispatch_manager::get_instance_references().get_dispatch_manager_id()*2+1)
+						{
+							return Error_code::SUCCESS;
+						}
+					}
+					else if ( t_dispatch_request_msg.dispatch_motion_direction() == message::Dispatch_motion_direction::E_PICKUP_CAR )
+					{
+						if ( t_dispatch_request_msg.id_struct().has_unit_id() &&
+						t_dispatch_request_msg.mutable_id_struct()->unit_id() == Dispatch_manager::get_instance_references().get_dispatch_manager_id() )
+						{
+							return Error_code::SUCCESS;
+						}
+					}
+				}
+				else
+				{
+					return Error_manager(Error_code::SYSTEM_EXECUTOR_PARSE_ERROR, Error_level::MINOR_ERROR,
+										 " message::Dispatch_request_msg  ParseFromString error ");
+				}
+				break;
+			}
+			case Communication_message::Message_type::eDispatch_plan_response_msg:
+			{
+				return Error_code::SUCCESS;
+				break;
+			}
+			case Communication_message::Message_type::eDispatch_control_request_msg:
+			{
+				return Error_code::SUCCESS;
+				break;
+			}
+			default :
+				;
+				break;
+		}
+	}
+
+	//检查接受人
+	if ( p_msg->get_receiver() == Communication_message::Communicator::eEmpty )
+	{
+		//检查消息类型
+		switch ( p_msg->get_message_type() )
+		{
+			case Communication_message::Message_type::eGround_status_msg:
+			{
+				message::Ground_status_msg t_ground_status_msg;
+				//针对消息类型, 对消息进行二次解析
+				if (t_ground_status_msg.ParseFromString(p_msg->get_message_buf()))
+				{
+					if ( t_ground_status_msg.mutable_id_struct()->terminal_id() == Dispatch_manager::get_instance_references().get_dispatch_manager_id()*2 ||
+					t_ground_status_msg.mutable_id_struct()->terminal_id() == Dispatch_manager::get_instance_references().get_dispatch_manager_id()*2+1)
+					{
+						return Error_code::SUCCESS;
+					}
+				}
+				else
+				{
+					return Error_manager(Error_code::SYSTEM_EXECUTOR_PARSE_ERROR, Error_level::MINOR_ERROR,
+										 " message::Dispatch_request_msg  ParseFromString error ");
+				}
+				break;
+			}
+			case Communication_message::Message_type::eTerminal_status_msg:
+			{
+				message::Terminal_status_msg t_terminal_status_msg;
+				//针对消息类型, 对消息进行二次解析
+				if (t_terminal_status_msg.ParseFromString(p_msg->get_message_buf()))
+				{
+                    if ( t_terminal_status_msg.id_struct().terminal_id() == Dispatch_manager::get_instance_references().get_dispatch_manager_id()*2 ||
+					t_terminal_status_msg.id_struct().terminal_id() == Dispatch_manager::get_instance_references().get_dispatch_manager_id()*2+1)
+					{
+                        return Error_code::SUCCESS;
+					}
+				}
+				else
+				{
+					return Error_manager(Error_code::SYSTEM_EXECUTOR_PARSE_ERROR, Error_level::MINOR_ERROR,
+										 " message::Dispatch_request_msg  ParseFromString error ");
+				}
+				break;
+			}
+			case Communication_message::Message_type::eNotify_status_msg:
+			{
+				message::Notify_status_msg t_notify_status_msg;
+
+				//针对消息类型, 对消息进行二次解析
+				if (t_notify_status_msg.ParseFromString(p_msg->get_message_buf()))
+				{
+					if ( t_notify_status_msg.mutable_id_struct()->terminal_id() == Dispatch_manager::get_instance_references().get_dispatch_manager_id()*2 ||
+					t_notify_status_msg.mutable_id_struct()->terminal_id() == Dispatch_manager::get_instance_references().get_dispatch_manager_id()*2+1)
+					{
+						return Error_code::SUCCESS;
+					}
+				}
+				else
+				{
+					return Error_manager(Error_code::SYSTEM_EXECUTOR_PARSE_ERROR, Error_level::MINOR_ERROR,
+										 " message::Dispatch_request_msg  ParseFromString error ");
+				}
+				break;
+			}
+			default :
+				;
+				break;
+		}
+	}
+
+	//无效的消息,
+	return Error_manager(Error_code::INVALID_MESSAGE, Error_level::NEGLIGIBLE_ERROR,
+						 " INVALID_MESSAGE error ");
+						 */
+}
+//检查执行者的状态, 判断能否处理这条消息,
+Error_manager System_executor::check_executer(Rabbitmq_message* p_msg)
+{
+	return Error_code::SUCCESS;
+	/*
+	if ( p_msg == NULL )
+	{
+		return Error_manager(Error_code::POINTER_IS_NULL, Error_level::MINOR_ERROR,
+							 "  POINTER IS NULL ");
+	}
+
+	//检查执行线程池
+	Error_manager t_executor_result = System_executor::get_instance_references().check_status();
+	if (t_executor_result.get_error_level() == NEGLIGIBLE_ERROR)//一级故障,轻微故障,
+	{
+		std::cout << "executer_is_busy , " << std::endl;
+		//返回繁忙之后, 通信模块1秒后再次调用check
+		return Error_code::COMMUNICATION_EXCUTER_IS_BUSY;
+	}
+	else if (t_executor_result.get_error_level() > NEGLIGIBLE_ERROR)
+	{
+		return Error_manager(Error_code::SYSTEM_EXECUTOR_STATUS_ERROR, Error_level::MINOR_ERROR,
+							"System_executor::get_instance_references().check_status(); fun error ");
+	}
+
+	//检查接受人
+	if ( p_msg->get_receiver() == Communication_message::Communicator::eDispatch_mamager )
+	{
+		return Dispatch_manager::get_instance_references().check_execute_msg(p_msg);
+	}
+*/
+	return Error_code::SUCCESS;
+
+}
+
+
+//处理消息的执行函数
+Error_manager System_executor::execute_msg(Rabbitmq_message* p_msg)
+{
+	if ( p_msg == NULL )
+	{
+		return Error_manager(Error_code::POINTER_IS_NULL, Error_level::MINOR_ERROR,
+							 "  POINTER IS NULL ");
+	}
+
+
+	return Dispatch_manager::get_instance_references().execute_rabbitmq_message_new(p_msg);
+
+
+//	//通过key来判断消息类型
+//	if ( p_msg->m_routing_key.find("count_command_signal") != p_msg->m_routing_key.npos ||
+//	p_msg->m_routing_key.find("count_command_signal") != p_msg->m_routing_key.npos)
+//	{
+//
+//	}
+//	else
+//	{
+//	    std::cout << " huli test :::: xxxxxxxxxxxxxxxxxxxxxxx" << " p_msg = " << p_msg->m_message_buf << std::endl;
+//	}
+
+
+
+	//不用解析, 直接给调度模块
+
+
+	/*
+	//检查接受人
+	if ( p_msg->get_receiver() == Communication_message::Communicator::eDispatch_mamager )
+	{
+		switch ( p_msg->get_message_type() )
+		{
+			case Communication_message::Message_type::eDispatch_request_msg:
+			{
+				message::Dispatch_request_msg t_dispatch_request_msg;
+				//针对消息类型, 对消息进行二次解析
+				if (t_dispatch_request_msg.ParseFromString(p_msg->get_message_buf()))
+				{
+					//往线程池添加执行任务, 之后会唤醒一个线程去执行他.
+					m_thread_pool.enqueue(&System_executor::execute_for_dispatch_request_msg, this,
+										  t_dispatch_request_msg	);
+				}
+				else
+				{
+					return Error_manager(Error_code::SYSTEM_EXECUTOR_PARSE_ERROR, Error_level::MINOR_ERROR,
+										 " message::Dispatch_request_msg  ParseFromString error ");
+				}
+				break;
+			}
+			case Communication_message::Message_type::eDispatch_plan_response_msg:
+			{
+				message::Dispatch_plan_response_msg t_dispatch_plan_response_msg;
+				//针对消息类型, 对消息进行二次解析
+				if (t_dispatch_plan_response_msg.ParseFromString(p_msg->get_message_buf()))
+				{
+					//往线程池添加执行任务, 之后会唤醒一个线程去执行他.
+					m_thread_pool.enqueue(&System_executor::execute_for_dispatch_plan_response_msg, this,
+										  t_dispatch_plan_response_msg	);
+				}
+				else
+				{
+					return Error_manager(Error_code::SYSTEM_EXECUTOR_PARSE_ERROR, Error_level::MINOR_ERROR,
+										 " message::Dispatch_request_msg  ParseFromString error ");
+				}
+				break;
+			}
+			case Communication_message::Message_type::eDispatch_control_request_msg:
+			{
+				message::Dispatch_control_request_msg t_dispatch_control_request_msg;
+				//针对消息类型, 对消息进行二次解析
+				if (t_dispatch_control_request_msg.ParseFromString(p_msg->get_message_buf()))
+				{
+					//往线程池添加执行任务, 之后会唤醒一个线程去执行他.
+					m_thread_pool.enqueue(&System_executor::execute_for_dispatch_control_request_msg, this,
+										  t_dispatch_control_request_msg	);
+				}
+				else
+				{
+					return Error_manager(Error_code::SYSTEM_EXECUTOR_PARSE_ERROR, Error_level::MINOR_ERROR,
+										 " message::Dispatch_request_msg  ParseFromString error ");
+				}
+				break;
+			}
+			default:
+				break;
+		}
+	}
+
+
+	//检查接受人
+	if ( p_msg->get_receiver() == Communication_message::Communicator::eEmpty )
+	{
+		switch ( p_msg->get_message_type() )
+		{
+			case Communication_message::Message_type::eGround_status_msg:
+			{
+				message::Ground_status_msg t_ground_status_msg;
+				//针对消息类型, 对消息进行二次解析
+				if (t_ground_status_msg.ParseFromString(p_msg->get_message_buf()))
+				{
+					//往线程池添加执行任务, 之后会唤醒一个线程去执行他.
+					m_thread_pool.enqueue(&System_executor::execute_for_ground_status_msg, this,
+										  t_ground_status_msg	);
+				}
+				else
+				{
+					return Error_manager(Error_code::SYSTEM_EXECUTOR_PARSE_ERROR, Error_level::MINOR_ERROR,
+										 " message::Dispatch_request_msg  ParseFromString error ");
+				}
+				break;
+			}
+			case Communication_message::Message_type::eTerminal_status_msg:
+			{
+				message::Terminal_status_msg t_terminal_status_msg;
+				//针对消息类型, 对消息进行二次解析
+				if (t_terminal_status_msg.ParseFromString(p_msg->get_message_buf()))
+				{
+					//往线程池添加执行任务, 之后会唤醒一个线程去执行他.
+					m_thread_pool.enqueue(&System_executor::execute_for_terminal_status_msg, this,
+										  t_terminal_status_msg	);
+				}
+				else
+				{
+					return Error_manager(Error_code::SYSTEM_EXECUTOR_PARSE_ERROR, Error_level::MINOR_ERROR,
+										 " message::Dispatch_request_msg  ParseFromString error ");
+				}
+				break;
+			}
+			case Communication_message::Message_type::eNotify_status_msg:
+			{
+				message::Notify_status_msg t_notify_status_msg;
+				//针对消息类型, 对消息进行二次解析
+				if (t_notify_status_msg.ParseFromString(p_msg->get_message_buf()))
+				{
+					//往线程池添加执行任务, 之后会唤醒一个线程去执行他.
+					m_thread_pool.enqueue(&System_executor::execute_for_notify_status_msg, this,
+										  t_notify_status_msg	);
+				}
+				else
+				{
+					return Error_manager(Error_code::SYSTEM_EXECUTOR_PARSE_ERROR, Error_level::MINOR_ERROR,
+										 " message::Dispatch_request_msg  ParseFromString error ");
+				}
+				break;
+			}
+			default:
+				break;
+		}
+	}
+*/
+
+	return Error_code::SUCCESS;
+}
+
+//检查状态
+Error_manager System_executor::check_status()
+{
+	if ( m_system_executor_status == SYSTEM_EXECUTOR_READY )
+	{
+		if ( m_thread_pool.thread_is_full_load() == false )
+		{
+		    return Error_code::SUCCESS;
+		}
+		else
+		{
+		    return Error_manager(Error_code::SYSTEM_EXECUTOR_STATUS_BUSY, Error_level::NEGLIGIBLE_ERROR,
+		    					" System_executor::check_status error ");
+		}
+	}
+	else
+	{
+		return Error_manager(Error_code::SYSTEM_EXECUTOR_STATUS_ERROR, Error_level::MINOR_ERROR,
+							" System_executor::check_status error ");
+	}
+}
+
+//定时发送状态信息
+Error_manager System_executor::encapsulate_send_status()
+{
+	Error_manager t_error;
+return Error_code::SUCCESS;
+
+	int t_dispatch_manager_id = Dispatch_manager::get_instance_references().get_dispatch_manager_id();
+	std::string t_msg;
+/*
+	//创建一条 调度管理总管理的状态
+	message::Dispatch_manager_status_msg t_dispatch_manager_status_msg;
+	t_dispatch_manager_status_msg.mutable_base_info()->set_msg_type(message::Message_type::eDispatch_manager_status_msg);
+	t_dispatch_manager_status_msg.mutable_base_info()->set_timeout_ms(5000);
+	t_dispatch_manager_status_msg.mutable_base_info()->set_sender(message::Communicator::eDispatch);
+	t_dispatch_manager_status_msg.mutable_base_info()->set_receiver(message::Communicator::eMain);
+
+	t_dispatch_manager_status_msg.set_dispatch_id(t_dispatch_id);
+
+	Dispatch_manager::Dispatch_manager_status t_dispatch_manager_status = Dispatch_manager::get_instance_references().get_dispatch_manager_status();
+	t_dispatch_manager_status_msg.set_dispatch_manager_status((message::Dispatch_manager_status)t_dispatch_manager_status);
+
+	t_msg = t_dispatch_manager_status_msg.SerializeAsString();
+	System_communication::get_instance_references().encapsulate_msg(t_msg);
+*/
+
+/*
+	//创建4条 调度模块终端出入口的状态
+	message::Dispatch_terminal_status_msg t_dispatch_terminal_status_msg;
+	t_dispatch_terminal_status_msg.mutable_base_info()->set_msg_type(message::Message_type::eDispatch_status_msg);
+	t_dispatch_terminal_status_msg.mutable_base_info()->set_timeout_ms(5000);
+	t_dispatch_terminal_status_msg.mutable_base_info()->set_sender(message::Communicator::eDispatch_manager);
+	t_dispatch_terminal_status_msg.mutable_base_info()->set_receiver(message::Communicator::eMain);
+	t_dispatch_terminal_status_msg.set_terminal_id(t_dispatch_manager_id*2+0);
+	t_dispatch_terminal_status_msg.set_terminal_status(message::Terminal_status::E_TERMINAL_READY);
+	t_dispatch_terminal_status_msg.set_passageway_direction(message::Passageway_direction::E_INLET);
+	t_msg = t_dispatch_terminal_status_msg.SerializeAsString();
+	System_communication::get_instance_references().encapsulate_msg(t_msg);
+
+	t_dispatch_terminal_status_msg.mutable_base_info()->set_msg_type(message::Message_type::eDispatch_status_msg);
+	t_dispatch_terminal_status_msg.mutable_base_info()->set_timeout_ms(5000);
+	t_dispatch_terminal_status_msg.mutable_base_info()->set_sender(message::Communicator::eDispatch_manager);
+	t_dispatch_terminal_status_msg.mutable_base_info()->set_receiver(message::Communicator::eMain);
+	t_dispatch_terminal_status_msg.set_terminal_id(t_dispatch_manager_id*2+0);
+	t_dispatch_terminal_status_msg.set_terminal_status(message::Terminal_status::E_TERMINAL_READY);
+	t_dispatch_terminal_status_msg.set_passageway_direction(message::Passageway_direction::E_OUTLET);
+	t_msg = t_dispatch_terminal_status_msg.SerializeAsString();
+	System_communication::get_instance_references().encapsulate_msg(t_msg);
+
+	t_dispatch_terminal_status_msg.mutable_base_info()->set_msg_type(message::Message_type::eDispatch_status_msg);
+	t_dispatch_terminal_status_msg.mutable_base_info()->set_timeout_ms(5000);
+	t_dispatch_terminal_status_msg.mutable_base_info()->set_sender(message::Communicator::eDispatch_manager);
+	t_dispatch_terminal_status_msg.mutable_base_info()->set_receiver(message::Communicator::eMain);
+	t_dispatch_terminal_status_msg.set_terminal_id(t_dispatch_manager_id*2+1);
+	t_dispatch_terminal_status_msg.set_terminal_status(message::Terminal_status::E_TERMINAL_READY);
+	t_dispatch_terminal_status_msg.set_passageway_direction(message::Passageway_direction::E_INLET);
+	t_msg = t_dispatch_terminal_status_msg.SerializeAsString();
+	System_communication::get_instance_references().encapsulate_msg(t_msg);
+
+	t_dispatch_terminal_status_msg.mutable_base_info()->set_msg_type(message::Message_type::eDispatch_status_msg);
+	t_dispatch_terminal_status_msg.mutable_base_info()->set_timeout_ms(5000);
+	t_dispatch_terminal_status_msg.mutable_base_info()->set_sender(message::Communicator::eDispatch_manager);
+	t_dispatch_terminal_status_msg.mutable_base_info()->set_receiver(message::Communicator::eMain);
+	t_dispatch_terminal_status_msg.set_terminal_id(t_dispatch_manager_id*2+1);
+	t_dispatch_terminal_status_msg.set_terminal_status(message::Terminal_status::E_TERMINAL_READY);
+	t_dispatch_terminal_status_msg.set_passageway_direction(message::Passageway_direction::E_OUTLET);
+	t_msg = t_dispatch_terminal_status_msg.SerializeAsString();
+	System_communication::get_instance_references().encapsulate_msg(t_msg);
+
+ */
+	return Error_code::SUCCESS;
+}
+
+//定时发送 调度管理的状态
+Error_manager System_executor::encapsulate_send_dispatch_manager_status()
+{
+//	return Dispatch_manager::get_instance_references().encapsulate_send_dispatch_manager_status();
+	return Dispatch_manager::get_instance_references().encapsulate_send_dispatch_manager_status_new();
+}
+
+
+//判断是否为待机,如果已经准备好,则可以执行任务。
+bool System_executor::is_ready()
+{
+	if ( m_system_executor_status == SYSTEM_EXECUTOR_READY && m_thread_pool.thread_is_full_load() == false )
+	{
+	    return true;
+	}
+	else
+	{
+		return false;
+	}
+}
+
+System_executor::System_executor_status System_executor::get_system_executor_status()
+{
+	return m_system_executor_status;
+}
+
+
+
+
+//雷达感测定位 的处理函数
+//input::command_id, 消息指令id, 由主控制系统生成的唯一码
+//input::command_id, 终端id, 对应具体的某个车位
+//return::void, 没有返回, 执行结果直接生成一条答复消息, 然后通过通信返回
+//void System_executor::execute_for_measure(std::string command_key, int unit_id, int terminal_id)
+//{
+//	Error_manager t_error;
+//
+//	LOG(INFO) << " System_executor::execute_for_measure run "<< this;
+//	//这里要处理.......以后再写
+//
+//	//创建一条答复消息
+//	message::Measure_response_msg t_measure_response_msg;
+//	t_measure_response_msg.mutable_base_info()->set_msg_type(message::Message_type::eLocate_response_msg);
+//	t_measure_response_msg.mutable_base_info()->set_timeout_ms(5000);
+//	t_measure_response_msg.mutable_base_info()->set_sender(message::Communicator::eMeasurer);
+//	t_measure_response_msg.mutable_base_info()->set_receiver(message::Communicator::eMain);
+//
+//	t_measure_response_msg.set_command_key(command_key);
+//	t_measure_response_msg.mutable_id_struct()->set_unit_id(unit_id);
+//	t_measure_response_msg.mutable_id_struct()->set_terminal_id(terminal_id);
+//	t_measure_response_msg.mutable_error_manager()->set_error_code(t_error.get_error_code());
+//	t_measure_response_msg.mutable_error_manager()->set_error_level((message::Error_level)t_error.get_error_level());
+//	t_measure_response_msg.mutable_error_manager()->set_error_description(t_error.get_error_description());
+//
+//	t_measure_response_msg.mutable_locate_information()->set_locate_x(0);
+//	t_measure_response_msg.mutable_locate_information()->set_locate_y(0);
+//	t_measure_response_msg.mutable_locate_information()->set_locate_angle(0);
+//	t_measure_response_msg.mutable_locate_information()->set_locate_length(0);
+//	t_measure_response_msg.mutable_locate_information()->set_locate_width(0);
+//	t_measure_response_msg.mutable_locate_information()->set_locate_height(0);
+//	t_measure_response_msg.mutable_locate_information()->set_locate_wheel_base(0);
+//	t_measure_response_msg.mutable_locate_information()->set_locate_wheel_width(0);
+//	t_measure_response_msg.mutable_locate_information()->set_locate_correct(0);
+//
+//	std::string t_msg = t_measure_response_msg.SerializeAsString();
+//	System_communication::get_instance_references().encapsulate_task_msg(t_msg);
+//	LOG(INFO) << " System_executor::execute_for_measure end "<< this;
+//
+//	return ;
+//}
+//
+//
+////调度模块的处理函数
+//void System_executor::execute_for_dispatch(std::string command_key, Dispatch_manager::Dispatch_motion_direction dispatch_motion_direction,
+//										   int terminal_id, int parkspace_id, Locate_information * p_locate_information)
+//{
+//	Error_manager t_error;
+//
+//	LOG(INFO) << " System_executor::execute_for_dispatch run "<< this;
+//	//这里要处理.......以后再写
+//
+//	t_error = Dispatch_manager::get_instance_references().execute_task(dispatch_motion_direction);
+//
+//	//创建一条答复消息
+//	message::Dispatch_response_msg t_dispatch_response_msg;
+//	t_dispatch_response_msg.mutable_base_info()->set_msg_type(message::Message_type::eDispatch_response_msg);
+//	t_dispatch_response_msg.mutable_base_info()->set_timeout_ms(5000);
+//	t_dispatch_response_msg.mutable_base_info()->set_sender(message::Communicator::eDispatch_manager);
+//	t_dispatch_response_msg.mutable_base_info()->set_receiver(message::Communicator::eMain);
+//
+//	t_dispatch_response_msg.set_command_key(command_key);
+//	t_dispatch_response_msg.mutable_error_manager()->set_error_code(t_error.get_error_code());
+//	t_dispatch_response_msg.mutable_error_manager()->set_error_level((message::Error_level)t_error.get_error_level());
+//	t_dispatch_response_msg.mutable_error_manager()->set_error_description(t_error.get_error_description());
+//
+//	std::string t_msg = t_dispatch_response_msg.SerializeAsString();
+//	System_communication::get_instance_references().encapsulate_task_msg(t_msg);
+//
+//	std::cout << "huli test dispatch_motion_direction = " << dispatch_motion_direction << std::endl;
+//	std::cout << "huli test error = " << t_error << std::endl;
+//
+//
+//	LOG(INFO) << " System_executor::execute_for_dispatch end "<< this;
+//	return ;
+//
+//}
+//
+////调度模块的处理函数
+//void System_executor::execute_for_dispatch_request_msg(message::Dispatch_request_msg dispatch_request_msg)
+//{
+//	Error_manager t_error;
+//	t_error = Dispatch_manager::get_instance_references().execute_for_dispatch_request_msg(dispatch_request_msg);
+//	if ( t_error != Error_code::SUCCESS )
+//	{
+//		LOG(INFO) << " System_executor::execute_for_dispatch_request_msg fun error "<< this;
+//		LOG(INFO) << t_error.to_string() << "   "<< this;
+//	}
+//	return;
+//}
+////调度模块 //调度总规划的答复(调度算法->调度管理)
+//void System_executor::execute_for_dispatch_plan_response_msg(message::Dispatch_plan_response_msg dispatch_plan_response_msg)
+//{
+//	Error_manager t_error;
+//	t_error = Dispatch_manager::get_instance_references().execute_for_dispatch_plan_response_msg(dispatch_plan_response_msg);
+//	if ( t_error != Error_code::SUCCESS )
+//	{
+//		LOG(INFO) << " System_executor::execute_for_dispatch_request_msg fun error "<< this;
+//		LOG(INFO) << t_error.to_string() << "   "<< this;
+//	}
+//	return;
+//}
+////调度模块 //调度控制的任务请求(调度算法->调度管理)
+//void System_executor::execute_for_dispatch_control_request_msg(message::Dispatch_control_request_msg dispatch_control_request_msg)
+//{
+//	Error_manager t_error;
+//	t_error = Dispatch_manager::get_instance_references().execute_for_dispatch_control_request_msg(dispatch_control_request_msg);
+//	if ( t_error != Error_code::SUCCESS )
+//	{
+//		LOG(INFO) << " System_executor::execute_for_dispatch_request_msg fun error "<< this;
+//		LOG(INFO) << t_error.to_string() << "   "<< this;
+//	}
+//	return;
+//}
+//
+////地面雷达的状态消息(地面雷达->null)
+//void System_executor::execute_for_ground_status_msg(message::Ground_status_msg ground_status_msg)
+//{
+//	Error_manager t_error;
+//	t_error = Dispatch_manager::get_instance_references().execute_for_ground_status_msg(ground_status_msg);
+//	if ( t_error != Error_code::SUCCESS )
+//	{
+//		LOG(INFO) << " System_executor::execute_for_dispatch_request_msg fun error "<< this;
+//		LOG(INFO) << t_error.to_string() << "   "<< this;
+//	}
+//	return ;
+//}
+//
+////地面雷达的状态消息(地面雷达->null)
+//void System_executor::execute_for_terminal_status_msg(message::Terminal_status_msg terminal_status_msg)
+//{
+//	Error_manager t_error;
+//	t_error = Dispatch_manager::get_instance_references().execute_for_singlechip_data_msg(terminal_status_msg.singlechipdata(), terminal_status_msg.singlechip_validity());
+//	if ( t_error != Error_code::SUCCESS )
+//	{
+//		LOG(INFO) << " System_executor::execute_for_singlechip_data_msg fun error "<< this;
+//		LOG(INFO) << t_error.to_string() << "   "<< this;
+//	}
+//	return ;
+//}
+//
+////调度模块 ///单片机的状态消息
+//void System_executor::execute_for_notify_status_msg(message::Notify_status_msg notify_status_msg)
+//{
+//  //  LOG(INFO) << "notify_status_msg = " << notify_status_msg.DebugString()<< this;
+//
+//
+//    Error_manager t_error;
+//	t_error = Dispatch_manager::get_instance_references().execute_for_singlechip_data_msg(notify_status_msg.singlechipdata(), notify_status_msg.singlechip_validity());
+//	if ( t_error != Error_code::SUCCESS )
+//	{
+//		LOG(INFO) << " System_executor::execute_for_singlechip_data_msg fun error "<< this;
+//		LOG(INFO) << t_error.to_string() << "   "<< this;
+//	}
+//	return ;
+//}
+

+ 110 - 0
plc调度节点/system/system_executor.h

@@ -0,0 +1,110 @@
+//
+// Created by huli on 2020/7/2.
+//
+
+#ifndef NNXX_TESTS_SYSTEM_EXECUTOR_H
+#define NNXX_TESTS_SYSTEM_EXECUTOR_H
+
+#include "../tool/thread_pool.h"
+#include "../tool/singleton.h"
+#include "../error_code/error_code.h"
+//#include "../communication/communication_message.h"
+#include "../dispatch/dispatch_manager.h"
+//#include "../locate/locate_manager.h"
+//#include "../locate/locate_manager_task.h"
+
+//#include "../message/measure_message.pb.h"
+//#include "../laser/laser_manager.h"
+//#include "../locate/locate_manager.h"
+#include "../system/system_communication.h"
+//#include "../message/dispatch_message.pb.h"
+//#include "../message/notify_message.pb.h"
+#include "../dispatch/dispatch_manager.h"
+#include "../rabbitmq/rabbitmq_message.h"
+
+
+class System_executor:public Singleton<System_executor>
+{
+// 子类必须把父类设定为友元函数,这样父类才能使用子类的私有构造函数。
+   friend class Singleton<System_executor>;
+
+public:
+	//系统执行者的状态
+	enum System_executor_status
+	{//default SYSTEM_EXECUTOR_UNKNOW = 0
+	    SYSTEM_EXECUTOR_UNKNOW				= 0,    //
+		SYSTEM_EXECUTOR_READY				= 1,    //
+
+		SYSTEM_EXECUTOR_FAULT				= 10,    //
+
+	};
+   
+private:
+ // 父类的构造函数必须保护,子类的构造函数必须私有。
+   System_executor();
+public:
+    //必须关闭拷贝构造和赋值构造,只能通过 get_instance 函数来进行操作唯一的实例。
+    System_executor(const System_executor& other) = delete;
+    System_executor& operator =(const System_executor& other) = delete;
+    ~System_executor();
+public://API functions
+	//初始化
+	Error_manager system_executor_init(int threads_size);
+	//反初始化
+	Error_manager system_executor_uninit();
+
+	//检查消息是否有效, 主要检查消息类型和接受者, 判断这条消息是不是给我的.
+	Error_manager check_msg(Rabbitmq_message* p_msg);
+	//检查执行者的状态, 判断能否处理这条消息,
+	Error_manager check_executer(Rabbitmq_message* p_msg);
+	//处理消息的执行函数
+	Error_manager execute_msg(Rabbitmq_message* p_msg);
+
+	//检查状态
+	Error_manager check_status();
+
+	//定时发送状态信息
+	Error_manager encapsulate_send_status();
+	//定时发送 调度管理的状态
+	Error_manager encapsulate_send_dispatch_manager_status();
+
+	//判断是否为待机,如果已经准备好,则可以执行任务。
+	bool is_ready();
+public://get or set member variable
+	System_executor_status get_system_executor_status();
+public:
+	//雷达感测定位 的处理函数
+//input::command_id, 消息指令id, 由主控制系统生成的唯一码
+//input::command_id, 终端id, 对应具体的某个车位
+//return::void, 没有返回, 执行结果直接生成一条答复消息, 然后通过通信返回
+//	void execute_for_measure(std::string command_key, int unit_id, int terminal_id);
+
+	//调度模块的处理函数
+//	void execute_for_dispatch(std::string command_key, Dispatch_manager::Dispatch_motion_direction dispatch_motion_direction,
+//							  int terminal_id, int parkspace_id, Locate_information * p_locate_information);
+
+	//调度模块 //执行搬运请求(主控->调度管理)
+//	void execute_for_dispatch_request_msg(message::Dispatch_request_msg dispatch_request_msg);
+	//调度模块 //调度总规划的答复(调度算法->调度管理)
+//	void execute_for_dispatch_plan_response_msg(message::Dispatch_plan_response_msg dispatch_plan_response_msg);
+	//调度模块 //调度控制的任务请求(调度算法->调度管理)
+//	void execute_for_dispatch_control_request_msg(message::Dispatch_control_request_msg dispatch_control_request_msg);
+
+	//地面雷达的状态消息(地面雷达->null)
+//	void execute_for_ground_status_msg(message::Ground_status_msg ground_status_msg);
+	//调度模块 ///单片机的状态消息
+//	void execute_for_terminal_status_msg(message::Terminal_status_msg terminal_status_msg);
+	//调度模块 ///单片机的状态消息
+//	void execute_for_notify_status_msg(message::Notify_status_msg notify_status_msg);
+protected://member variable
+
+	System_executor_status		m_system_executor_status;		//系统执行者的状态
+	
+	Thread_pool 				m_thread_pool;					//执行多任务的线程池
+
+private:
+
+};
+
+
+#endif //NNXX_TESTS_SYSTEM_EXECUTOR_H

+ 193 - 0
plc调度节点/task/task_base.cpp

@@ -0,0 +1,193 @@
+//
+// Created by zx on 2019/12/28.
+//
+
+#include "task_base.h"
+#include "../error_code/error_code.h"
+
+Task_Base::Task_Base()
+{
+	static unsigned int t_task_id = 0;
+	m_task_id = t_task_id;
+	t_task_id++;
+
+    m_task_type = UNKNOW_TASK;
+	m_task_statu = TASK_CREATED;
+	mp_tast_receiver = NULL;
+
+	m_task_start_time = std::chrono::system_clock::now();	//获取当前时间
+	m_task_over_time = std::chrono::milliseconds(TASK_OVER_TIME_DEFAULT); //默认10秒
+}
+Task_Base::~Task_Base()
+{
+	mp_tast_receiver = NULL;
+}
+
+
+//初始化任务单,必须初始化之后才可以使用,
+//    input:tast_receiver 接受对象
+//    input:task_over_time 超时时间
+Error_manager Task_Base::task_init(void* p_tast_receiver,
+						std::chrono::milliseconds task_over_time)
+{
+	m_task_statu = TASK_CREATED;
+	m_task_statu_information = "";
+	mp_tast_receiver = p_tast_receiver;
+	m_task_over_time = task_over_time;
+	m_task_error_manager.error_manager_clear_all();
+	return Error_code::SUCCESS;
+}
+
+//初始化任务单,必须初始化之后才可以使用,
+//    input:task_statu 任务状态
+//    input:task_statu_information 状态说明
+//    input:tast_receiver 接受对象
+//    input:task_over_time 超时时间
+Error_manager Task_Base::task_init(Task_statu task_statu,
+				   std::string task_statu_information,
+				   void* p_tast_receiver,
+				   std::chrono::milliseconds task_over_time)
+{
+	m_task_statu = task_statu;
+	m_task_statu_information = task_statu_information;
+	mp_tast_receiver = p_tast_receiver;
+	m_task_over_time = task_over_time;
+	m_task_error_manager.error_manager_clear_all();
+	return Error_code::SUCCESS;
+}
+
+//任务单重置, 相当于重新创建, 会重置时间和错误码.
+Error_manager Task_Base::task_reset()
+{
+	//m_task_id不变	//m_task_type不变 //因为这个是创建的时候就定好的
+	m_task_statu = TASK_CREATED;
+	m_task_statu_information.clear();
+	mp_tast_receiver = NULL;
+
+	m_task_start_time = std::chrono::system_clock::now();	//获取当前时间
+	m_task_over_time = std::chrono::milliseconds(TASK_OVER_TIME_DEFAULT); //默认10秒
+
+	m_task_error_manager.error_manager_clear_all();
+	return Error_code::SUCCESS;
+}
+
+//更新任务单
+//task_statu: 任务状态
+//statu_information:状态说明
+Error_manager Task_Base::update_statu(Task_statu task_statu,std::string statu_information)
+{
+    m_task_statu=task_statu;
+    m_task_statu_information=statu_information;
+    return SUCCESS;
+}
+
+//判断是否超时。返回true表示任务超时,返回false表示任务没有超时
+bool Task_Base::is_over_time()
+{
+	return (std::chrono::system_clock::now() - m_task_start_time) > m_task_over_time;
+}
+
+//判断是否结束, TASK_OVER  TASK_ERROR TASK_DEAD 都算结束
+bool Task_Base::is_task_end()
+{
+	if(m_task_statu == TASK_OVER || m_task_statu == TASK_ERROR || m_task_statu == TASK_DEAD)
+	{
+		return true;
+	}
+	else
+	{
+	    return false;
+	}
+}
+
+
+
+
+//获取 任务单id
+unsigned int  Task_Base::get_task_id()
+{
+	return m_task_id;
+}
+
+//获取任务类型
+Task_Base::Task_type Task_Base::get_task_type()
+{
+    return m_task_type;
+}
+//获取任务单状态
+Task_Base::Task_statu  Task_Base::get_task_statu()
+{
+    return m_task_statu;
+}
+//设置 任务单状态
+void  Task_Base::set_task_statu(Task_statu task_statu)
+{
+	m_task_statu = task_statu;
+}
+
+
+//获取状态说明
+std::string Task_Base::get_task_statu_information()
+{
+    return m_task_statu_information;
+}
+//设置 状态说明
+void Task_Base::set_task_statu_information(std::string task_statu_information)
+{
+	m_task_statu_information = task_statu_information;
+}
+//获取 错误码,返回引用。
+Error_manager& Task_Base::get_task_error_manager()
+{
+	return m_task_error_manager;
+}
+//设置 错误码
+void Task_Base::set_task_error_manager(Error_manager & error_manager)
+{
+	m_task_error_manager = error_manager;
+}
+//比较覆盖错误码
+void Task_Base::compare_and_cover_task_error_manager(Error_manager & error_manager)
+{
+	m_task_error_manager.compare_and_cover_error(error_manager);
+}
+
+
+
+
+
+//获取任务接收方
+void * Task_Base::get_tast_receiver()
+{
+	return mp_tast_receiver;
+}
+//设置任务接收方
+void Task_Base::set_tast_receiver(void * p_tast_receiver)
+{
+	mp_tast_receiver = p_tast_receiver;
+}
+
+
+//获取 任务创建的时间点
+std::chrono::system_clock::time_point Task_Base::get_task_start_time()
+{
+	return m_task_start_time;
+}
+//设置 任务创建的时间点
+void Task_Base::set_task_start_time(std::chrono::system_clock::time_point task_start_time)
+{
+	m_task_start_time = task_start_time;
+}
+//获取 任务超时的时限
+std::chrono::milliseconds	Task_Base::get_task_over_time()
+{
+	return m_task_over_time;
+}
+//设置 任务超时的时限
+void	Task_Base::set_task_over_time(std::chrono::milliseconds task_over_time)
+{
+	m_task_over_time = task_over_time;
+}
+
+
+

+ 163 - 0
plc调度节点/task/task_base.h

@@ -0,0 +1,163 @@
+/*
+ * Task_Base 是任务基类,用作不同的模块之间的通信载体。
+ *	每一个模块创建一个任务子类,从Task_Base继承。
+ *	然后任务子类自定义一些数据和读写数据的接口函数。
+ *	然后在任务接受方实现 execute_task(Task_Base* p_laser_task)
+ * */
+
+#ifndef TASK_BASE_H
+#define TASK_BASE_H
+#include <string>
+#include "../error_code/error_code.h"
+#include <chrono>
+#include <atomic>
+
+//任务单基类
+class Task_Base
+{
+
+public:
+
+//任务超时时间默认值10000ms,10秒
+#define TASK_OVER_TIME_DEFAULT				10000
+
+//任务类型
+	enum Task_type
+	{
+		UNKNOW_TASK             =0,				//未知任务单//初始化,默认值
+		LASER_MANGER_SCAN_TASK  =1,             //雷达管理模块的扫描任务,
+		LASER_BASE_SCAN_TASK    =2,             //单个雷达的扫描任务,
+		LOCATE_MANGER_TASK		=3,             //测量任务
+		PLC_TASK                =4,             //上传PLC任务
+
+		WANJI_MANAGER_TASK,						//万集雷达管理任务
+		WANJI_LIDAR_SCAN,						//万集雷达扫描任务
+		WANJI_LIDAR_DETECT,						//万集雷达定位任务
+
+
+	VELODYNE_MANAGER_TASK,						//velodyne雷达管理任务
+	VELODYNE_LIDAR_SCAN,						//velodyne雷达扫描任务
+	VELODYNE_LIDAR_DETECT,						//velodyne雷达定位任务
+
+
+		DISPATCH_MANAGER_TASK,					//调度管理任务
+		CARRIER_TASK,							//搬运器任务
+		CATCHER_TASK,							//抓取器任务
+		PASSAGEWAY_TASK,						//通道口任务
+
+	};
+//任务状态,如果任务故障,任务状态改为TASK_OVER,然后在m_task_error_manager 补充错误码。
+	enum Task_statu
+	{
+		TASK_CREATED            = 0,      		//任务创建, 发送方
+
+		TASK_ISSUE				= 1, 			//任务下发, 发送方
+		TASK_SIGNED             = 2,      		//已签收, 接收方
+		TASK_WORKING            = 3,      		//处理中, 接收方
+		TASK_OVER               = 4,   			//已结束, 接收方
+		TASK_STOP				= 5, 			//任务暂停, 接收方
+
+		TASK_ERROR              = 11,			//任务错误, 接收方
+
+		TASK_CANCEL				= 21,			//任务取消, 发送方
+		TASK_DEAD               = 22,           //任务死亡, 接收方
+
+		TASK_WITHDRAW			= 31, 			//任务收回, 发送方
+		TASK_FREE				= 32, 			//任务释放, 接收方
+
+	};
+protected:
+	//不允许构造基类,只允许子类构造,(多态)
+	Task_Base();
+public:
+    ~Task_Base();
+
+	//初始化任务单,必须初始化之后才可以使用,
+	//    input:tast_receiver 接受对象
+	//    input:task_over_time 超时时间
+	Error_manager task_init(void* p_tast_receiver,
+							std::chrono::milliseconds task_over_time);
+
+	//初始化任务单,必须初始化之后才可以使用,
+	//    input:task_statu 任务状态
+	//    input:task_statu_information 状态说明
+	//    input:tast_receiver 接受对象
+	//    input:task_over_time 超时时间
+	Error_manager task_init(Task_statu task_statu,
+					   std::string task_statu_information,
+					   void* p_tast_receiver,
+					   std::chrono::milliseconds task_over_time);
+
+	//任务单重置, 相当于重新创建, 会重置时间和错误码.
+	Error_manager task_reset();
+
+	//更新任务单
+    //task_statu: 任务状态
+    //statu_information:状态说明
+    Error_manager update_statu(Task_statu task_statu,std::string statu_information="");
+
+    //判断是否超时。返回true表示任务超时,返回false表示任务没有超时
+    bool is_over_time();
+
+	//判断是否结束, TASK_OVER  TASK_ERROR TASK_DEAD 都算结束
+	bool is_task_end();
+
+public:
+
+	//获取 任务单id
+	unsigned int  get_task_id();
+	//设置 任务单id
+//	void  set_task_id(unsigned int task_id) = delete;
+
+    //获取 任务类型
+    Task_type   get_task_type();
+	//设置 任务类型
+//	void   set_task_type(Task_type task_type) = delete;
+    //获取 任务单状态
+    Task_statu  get_task_statu();
+	//设置 任务单状态
+	void  set_task_statu(Task_statu task_statu);
+
+    //获取 状态说明
+    std::string get_task_statu_information();
+	//设置 状态说明
+	void set_task_statu_information(std::string task_statu_information);
+	//获取 错误码,返回引用。
+	Error_manager& get_task_error_manager();
+	//设置 错误码
+	void set_task_error_manager(Error_manager & error_manager);
+	//比较覆盖错误码
+	void compare_and_cover_task_error_manager(Error_manager & error_manager);
+
+	//获取任务接收方
+	void * get_tast_receiver();
+	//设置任务接收方
+	void set_tast_receiver(void * p_tast_receiver);
+	//获取 任务创建的时间点
+	std::chrono::system_clock::time_point get_task_start_time();
+	//设置 任务创建的时间点
+	void set_task_start_time(std::chrono::system_clock::time_point task_start_time);
+	//获取 任务超时的时限
+	std::chrono::milliseconds	get_task_over_time();
+	//设置 任务超时的时限
+	void	set_task_over_time(std::chrono::milliseconds task_over_time);
+
+
+protected:
+	unsigned int				m_task_id;						//任务id, 每次新建任务, 自动+1, 用于多任务的管理
+    Task_type                   m_task_type;					//任务类型,不允许中途修改
+	std::atomic<Task_statu>     m_task_statu;					//任务状态
+    std::string					m_task_statu_information;		//任务状态说明
+    void*						mp_tast_receiver;				//任务接收方,Task_Base并不分配和释放内存。
+    //注:mp_tast_receiver是可选的,可以为NULL。如果为NULL,则需要task_command_manager去找到接收对象。
+
+	std::chrono::system_clock::time_point 	m_task_start_time;	//任务创建的时间点
+	std::chrono::milliseconds	m_task_over_time;				//任务超时的时限
+	//注:std::chrono::system_clock::now();	//获取当前时间
+
+	//错误码,任务故障信息,任务输出
+	Error_manager               m_task_error_manager;
+};
+
+#endif //TASK_BASE_H
+

+ 80 - 0
plc调度节点/task/task_base.puml

@@ -0,0 +1,80 @@
+@startuml
+@startuml
+skinparam classAttributeIconSize 0
+
+
+title  Task_Base 任务单基类
+
+
+
+
+enum Task_type
+{
+//任务类型
+	UNKNOW_TASK             =0,				//未知任务单//初始化,默认值
+	LASER_TASK              =1,             //雷达扫描任务,
+    LOCATE_TASK             =2,             //测量任务
+    PLC_TASK                =3,             //上传PLC任务
+}
+
+
+enum Task_statu
+{
+//任务状态,如果任务故障,任务状态改为TASK_OVER,然后在m_task_error_manager 补充错误码。
+    TASK_CREATED            =0,             //创建状态,默认值
+    TASK_SIGNED             =1,             //已签收
+    TASK_WORKING            =2,             //处理中
+    TASK_OVER               =3,             //已结束
+}
+
+
+
+
+class Task_Base
+{
+//任务单基类
+==public:==
+    ~Task_Base();
+..
+    //初始化任务单,初始任务单类型为 UNKONW_TASK
+    virtual Error_manager init();
+..
+    //更新任务单
+    //task_statu: 任务状态
+    //statu_information:状态说明
+    Error_manager update_statu(Task_statu task_statu,std::string statu_information="");
+..
+    //获取任务类型
+    Task_type   get_task_type();
+..
+    //获取任务单状态
+    Task_statu  get_statu();
+..
+    //获取状态说明
+    std::string get_statu_information();
+..
+	//获取 错误码
+	Error_manager& get_task_error_manager();
+..
+	//设置 错误码
+	void set_task_error_manager(Error_manager & error_manager);
+==protected:==
+    Task_Base();
+==protected:==
+    Task_type                   m_task_type;                    //任务类型
+    Task_statu                  m_task_statu;                   //任务状态
+    std::string                 m_task_statu_information;       //任务状态说明
+	//错误码,任务故障信息,任务输出
+	Error_manager               m_task_error_manager;
+}
+
+class Error_manager
+{
+//错误码管理
+}
+Task_Base <-- Error_manager : include
+
+
+Task_Base <-- Task_type : include
+Task_Base <-- Task_statu : include
+@enduml

+ 56 - 0
plc调度节点/task/task_command_manager.cpp

@@ -0,0 +1,56 @@
+
+
+
+#include "task_command_manager.h"
+
+
+//对外的接口函数,所有的任务发送方,都必须使用该函数。
+//execute_task在内部解析了Task_Base里面的Task_type,然后转发给具体某个模块的实例对象。
+//input:p_task_base 任务单,基类的指针,指向子类的实例,(多态)
+Error_manager Task_command_manager::execute_task(Task_Base* p_task_base)
+{
+	Error_manager t_error;
+	void * tp_tast_receiver = p_task_base->get_tast_receiver();
+	switch ( p_task_base->get_task_type() )
+	{
+		case Task_Base::Task_type::UNKNOW_TASK:
+			t_error.error_manager_reset(Error_code::TASK_TYPE_IS_UNKNOW, Error_level::MINOR_ERROR,
+								" p_task_base->get_task_type() is  UNKNOW_TASK ");
+	        break;
+		case Task_Base::Task_type::LASER_MANGER_SCAN_TASK:
+			break;
+		case Task_Base::Task_type::LASER_BASE_SCAN_TASK:
+	        break;
+		case Task_Base::Task_type::LOCATE_MANGER_TASK:
+			break;
+		case Task_Base::Task_type::PLC_TASK:
+			break;
+		case Task_Base::Task_type::WANJI_MANAGER_TASK:
+			break;
+	    default:
+			t_error.error_manager_reset(Error_code::TASK_TYPE_IS_UNKNOW, Error_level::MINOR_ERROR,
+										" p_task_base->get_task_type() is  UNKNOW_TASK ");
+	        break;
+	}
+
+	return t_error;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+ 42 - 0
plc调度节点/task/task_command_manager.h

@@ -0,0 +1,42 @@
+/*
+ * task_command_manager 是任务单的总管理,单例模式
+ * 负责管理任务单的派送和转发
+ * 所有的任务发送方都只需要调用 task_command_manager.get_instance_references().execute_task(p_task_base)
+ * 然后task_command_manager去找到对应的接受对象,来调用该对象的接口函数。 例如Laser_base::execute_task
+ * 这样发送方和接收方不直接绑定,双方完全独立。
+ * 没有在实例里面保存对方的回调函数或者对象指针
+ *
+ * */
+
+#ifndef TASK_COMAND_MANAGER_H
+#define TASK_COMAND_MANAGER_H
+#include <string>
+#include "../error_code/error_code.h"
+#include "../task/task_base.h"
+#include "../tool/singleton.h"
+
+
+class Task_command_manager:public Singleton<Task_command_manager>
+{
+// 子类必须把父类设定为友元函数,这样父类才能使用子类的私有构造函数。
+	friend class Singleton<Task_command_manager>;
+public:
+// 必须关闭拷贝构造和赋值构造,只能通过 get_instance 函数来进行操作唯一的实例。
+	Task_command_manager(const Task_command_manager&)=delete;
+	Task_command_manager& operator =(const Task_command_manager&)= delete;
+	~Task_command_manager()=default;
+private:
+// 父类的构造函数必须保护,子类的构造函数必须私有。
+	Task_command_manager()=default;
+
+public:
+	//对外的接口函数,所有的任务发送方,都必须使用该函数。
+	//execute_task在内部解析了Task_Base里面的Task_type,然后转发给具体某个模块的实例对象。
+	//input:p_task_base 任务单,基类的指针,指向子类的实例,(多态)
+	Error_manager execute_task(Task_Base* p_task_base);
+};
+
+
+
+#endif //TASK_COMAND_MANAGER_H
+

+ 12 - 0
plc调度节点/task/task_command_manager.puml

@@ -0,0 +1,12 @@
+@startuml
+@startuml
+skinparam classAttributeIconSize 0
+
+
+title  task_command_manager 任务单管理类
+
+
+
+
+
+@enduml

+ 33 - 0
plc调度节点/tool/TaskQueue/BaseTask.cpp

@@ -0,0 +1,33 @@
+//
+//  BaseTaskQueue.cpp
+//  LibDriveRating-CXX
+//
+//  Created by Melo Yao on 6/9/14.
+//  Copyright (c) 2014 AutoNavi. All rights reserved.
+//
+
+#include "BaseTask.h"
+
+namespace tq {
+    BaseTask::BaseTask():ITask(),_cancelled(false)
+    {
+    }
+    
+    void BaseTask::Cancel()
+    {
+        _cancelled = true;
+    }
+    
+    bool BaseTask::IsCancelled() const
+    {
+        return _cancelled;
+    }
+    
+    void BaseTask::Run()
+    {
+        if (_cancelled) {
+            return;
+        }
+        Main();
+    }
+}

+ 29 - 0
plc调度节点/tool/TaskQueue/BaseTask.h

@@ -0,0 +1,29 @@
+//
+//  BaseTaskQueue.h
+//  LibDriveRating-CXX
+//
+//  Created by Melo Yao on 6/9/14.
+//  Copyright (c) 2014 AutoNavi. All rights reserved.
+//
+
+#ifndef __LibDriveRating_CXX__BaseTaskQueue__
+#define __LibDriveRating_CXX__BaseTaskQueue__
+
+#include "TQInterface.h"
+namespace tq
+{
+    class BaseTask : public ITask
+    {
+    private:
+        volatile bool _cancelled;
+    public:
+        BaseTask();
+        void Run();
+        virtual void Cancel();
+        bool IsCancelled() const;
+        
+        virtual void Main() = 0;
+        TaskCategory GetCategory() const {return NoCategory;}
+    };
+}
+#endif /* defined(__LibDriveRating_CXX__BaseTaskQueue__) */

+ 23 - 0
plc调度节点/tool/TaskQueue/TQFactory.cpp

@@ -0,0 +1,23 @@
+//
+//  TQFactory.cpp
+//  LibDriveRating-CXX
+//
+//  Created by Melo Yao on 6/10/14.
+//  Copyright (c) 2014 AutoNavi. All rights reserved.
+//
+
+#include "TQFactory.h"
+#include "ThreadTaskQueue.h"
+namespace tq {
+    IQueue* TQFactory::CreateDefaultQueue()
+    {
+        return new ThreadTaskQueue();
+    }
+    
+    void TQFactory::ReleaseQueue(IQueue* queue)
+    {
+        delete queue;
+    }
+    
+    
+}

+ 24 - 0
plc调度节点/tool/TaskQueue/TQFactory.h

@@ -0,0 +1,24 @@
+//
+//  TQFactory.h
+//  LibDriveRating-CXX
+//
+//  Created by Melo Yao on 6/10/14.
+//  Copyright (c) 2014 AutoNavi. All rights reserved.
+//
+
+#ifndef __LibDriveRating_CXX__TQFactory__
+#define __LibDriveRating_CXX__TQFactory__
+
+#include "TQInterface.h"
+
+namespace tq {
+    class TQFactory
+    {
+    public:
+        static IQueue* CreateDefaultQueue();
+
+        static void ReleaseQueue(IQueue* queue);
+    };
+}
+
+#endif /* defined(__LibDriveRating_CXX__TQFactory__) */

+ 58 - 0
plc调度节点/tool/TaskQueue/TQInterface.h

@@ -0,0 +1,58 @@
+//
+//  TQInterface.h
+//  LibDriveRating-CXX
+//
+//  Created by Melo Yao on 6/9/14.
+//  Copyright (c) 2014 AutoNavi. All rights reserved.
+//
+
+#ifndef __LibDriveRating_CXX__TQInterface__
+#define __LibDriveRating_CXX__TQInterface__
+
+namespace tq {
+    typedef unsigned long TaskCategory;
+
+    const TaskCategory NoCategory = 0;
+
+    class ITask
+    {
+    public:
+        virtual void Run() = 0;
+        virtual void Cancel() = 0;
+        virtual bool IsCancelled() const = 0;
+        virtual TaskCategory GetCategory() const = 0;
+        virtual ~ITask(){}
+    };
+    
+    typedef void (*TaskRecycler)(ITask* task,void* context);
+
+    class IQueue
+    {
+    public:
+        virtual void Start(unsigned int nThreads = 1) = 0;
+
+        virtual void Stop() = 0;
+
+        virtual void AddTask(ITask* task) = 0;
+        
+        virtual void GetTasks(ITask** tasksBuf, unsigned int taskBufSize) const= 0;
+        
+        virtual unsigned int TaskCount() const = 0;
+        
+        virtual void CancelAll() = 0;
+        
+        virtual void WaitForFinish() = 0;
+
+        virtual void Suspend() = 0;
+        
+        virtual void Resume() = 0;
+        
+        virtual void SetTaskRecycler(TaskCategory cat, TaskRecycler recycler,void *context){}
+
+        virtual void ClearTaskRecycler(TaskCategory cat){}
+
+        virtual ~IQueue() {}
+    };
+}
+
+#endif /* defined(__LibDriveRating_CXX__TQInterface__) */

+ 0 - 0
plc调度节点/tool/TaskQueue/TaskPool.h


برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است