Merge branch 'master' of http://8.140.179.55:20000/r/pipIrr-SV
| | |
| | | public Byte meter ;//流量计故障 |
| | | public Byte valve ;//阀门 |
| | | |
| | | public boolean hasAlarm(){ |
| | | boolean flag = false ; |
| | | if((batteryVolt != null && batteryVolt == 1) || |
| | | (loss != null && loss == 1) || |
| | | (meter != null && meter == 1) || |
| | | (valve != null && valve == 1)){ |
| | | flag = true ; |
| | | } |
| | | return flag ; |
| | | } |
| | | |
| | | public String alarmContent(){ |
| | | String txt = "" ; |
| | | if(batteryVolt != null && batteryVolt == 1){ |
| | | txt += "蓄电池电压报警" ; |
| | | } |
| | | if(meter != null && meter == 1){ |
| | | txt += ",流量计故障报警" ; |
| | | } |
| | | if(valve != null && valve == 1){ |
| | | txt += ",阀门故障报警" ; |
| | | } |
| | | if(loss != null && loss == 1){ |
| | | txt += ",漏损报警" ; |
| | | } |
| | | return txt ; |
| | | } |
| | | |
| | | public String toString(){ |
| | | StringBuilder str = new StringBuilder() ; |
| | | str.append(" 报警:\n"); |
| | |
| | | */ |
| | | public interface Pool{ |
| | | /** |
| | | * 线程池中线程个数 |
| | | * @return |
| | | */ |
| | | public Integer size() ; |
| | | public Integer maxThread() ; |
| | | public Integer minThread() ; |
| | | /** |
| | | * 把所要执行的工作对象实例放入线程池中 |
| | | * @param job ThreadJob 工作对象实例 |
| | | * @throws Exception |
| | |
| | | this.monitorThread.start() ; |
| | | } |
| | | } |
| | | /** |
| | | * 线程池中线程个数 |
| | | * @return |
| | | */ |
| | | @Override |
| | | public Integer size() { |
| | | return currNum ; |
| | | } |
| | | @Override |
| | | public Integer maxThread() { |
| | | return maxNum ; |
| | | } |
| | | @Override |
| | | public Integer minThread() { |
| | | return minNum ; |
| | | } |
| | | |
| | | /** |
| | | * 把所要执行的工作对象实例放入线程池中 |
| | |
| | | |
| | | private static ThreadPool.Pool pool_short ;//短工作任务线程池,线程工作用时较短 |
| | | private static ThreadPool.Pool pool_long ;//长工作任务线程池,线程工作用时较长 |
| | | |
| | | |
| | | |
| | | public final static Integer[] pool_short_state(){ |
| | | Integer shortCurThread = 0 ;//短线程池当前线程数 |
| | | Integer shortMaxThread = 0 ;//短线程池最大线程数 |
| | | Integer shortMinThread = 0 ;//短线程池最小线程数 |
| | | shortCurThread = pool_short.size() ; |
| | | shortMaxThread = pool_short.maxThread() ; |
| | | shortMinThread = pool_short.minThread() ; |
| | | return new Integer[]{shortCurThread, shortMaxThread, shortMinThread} ; |
| | | } |
| | | |
| | | public final static Integer[] pool_long_state(){ |
| | | Integer longCurThread = 0 ;//短线程池当前线程数 |
| | | Integer longMaxThread = 0 ;//短线程池最大线程数 |
| | | Integer longMinThread = 0 ;//短线程池最小线程数 |
| | | longCurThread = pool_long.size() ; |
| | | longMaxThread = pool_long.maxThread() ; |
| | | longMinThread = pool_long.minThread() ; |
| | | return new Integer[]{longCurThread, longMaxThread, longMinThread} ; |
| | | } |
| | | /** |
| | | * 初始化线程池 |
| | | * @param poolName 线程池和线程名称 |
| | |
| | | <artifactId>okhttp</artifactId> |
| | | <version>4.9.2</version> |
| | | </dependency> |
| | | |
| | | <!--钉钉消息推送--> |
| | | <dependency> |
| | | <groupId>com.aliyun</groupId> |
| | | <artifactId>alibaba-dingtalk-service-sdk</artifactId> |
| | | <version>2.0.0</version> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>commons-codec</groupId> |
| | | <artifactId>commons-codec</artifactId> |
| | | <version>1.15</version> |
| | | </dependency> |
| | | </dependencies> |
| | | |
| | | <build> |
New file |
| | |
| | | package com.dy.pipIrrGlobal.config; |
| | | |
| | | import com.dingtalk.api.DefaultDingTalkClient; |
| | | import com.dingtalk.api.DingTalkClient; |
| | | import com.dingtalk.api.request.OapiRobotSendRequest; |
| | | import com.dingtalk.api.response.OapiRobotSendResponse; |
| | | import com.taobao.api.ApiException; |
| | | import org.apache.commons.codec.binary.Base64; |
| | | import org.springframework.beans.factory.annotation.Value; |
| | | import org.springframework.stereotype.Component; |
| | | |
| | | import javax.crypto.Mac; |
| | | import javax.crypto.spec.SecretKeySpec; |
| | | import java.io.UnsupportedEncodingException; |
| | | import java.net.URLEncoder; |
| | | import java.security.InvalidKeyException; |
| | | import java.security.NoSuchAlgorithmException; |
| | | import java.util.Collections; |
| | | |
| | | /** |
| | | * @author ZhuBaoMin |
| | | * @date 2024-07-31 9:20 |
| | | * @LastEditTime 2024-07-31 9:20 |
| | | * @Description 钉钉客户端工具类 |
| | | */ |
| | | |
| | | @Component |
| | | public class DingTalk { |
| | | @Value("${dingtalk.robot.url}") |
| | | private String URL; |
| | | |
| | | @Value("${dingtalk.robot.access-token}") |
| | | private String CUSTOM_ROBOT_TOKEN; |
| | | |
| | | @Value("${dingtalk.robot.secret}") |
| | | private String SECRET; |
| | | |
| | | @Value("${dingtalk.at-all}") |
| | | private Boolean AT_ALL; |
| | | |
| | | @Value("${dingtalk.mobile}") |
| | | private String MOBILE; |
| | | |
| | | public void sendMessage(String message) { |
| | | try { |
| | | Long timestamp = System.currentTimeMillis(); |
| | | String secret = SECRET; |
| | | String stringToSign = timestamp + "\n" + secret; |
| | | Mac mac = Mac.getInstance("HmacSHA256"); |
| | | mac.init(new SecretKeySpec(secret.getBytes("UTF-8"), "HmacSHA256")); |
| | | byte[] signData = mac.doFinal(stringToSign.getBytes("UTF-8")); |
| | | String sign = URLEncoder.encode(new String(Base64.encodeBase64(signData)), "UTF-8"); |
| | | |
| | | //sign字段和timestamp字段必须拼接到请求URL上,否则会出现 310000 的错误信息 |
| | | DingTalkClient client = new DefaultDingTalkClient( URL + "?sign=" + sign + "×tamp=" + timestamp); |
| | | OapiRobotSendRequest req = new OapiRobotSendRequest(); |
| | | /** |
| | | * 发送文本消息 |
| | | */ |
| | | //定义文本内容 |
| | | OapiRobotSendRequest.Text text = new OapiRobotSendRequest.Text(); |
| | | text.setContent(message); |
| | | //定义 @对象 |
| | | OapiRobotSendRequest.At at = new OapiRobotSendRequest.At(); |
| | | if(AT_ALL) { |
| | | at.setIsAtAll(true); |
| | | }else { |
| | | at.setAtMobiles(Collections.singletonList(MOBILE)); |
| | | } |
| | | //设置消息类型 |
| | | req.setMsgtype("text"); |
| | | req.setText(text); |
| | | req.setAt(at); |
| | | OapiRobotSendResponse rsp = client.execute(req, CUSTOM_ROBOT_TOKEN); |
| | | System.out.println(rsp.getBody()); |
| | | } catch (ApiException e) { |
| | | e.printStackTrace(); |
| | | } catch (UnsupportedEncodingException e) { |
| | | throw new RuntimeException(e); |
| | | } catch (NoSuchAlgorithmException e) { |
| | | throw new RuntimeException(e); |
| | | } catch (InvalidKeyException e) { |
| | | throw new RuntimeException(e); |
| | | } |
| | | } |
| | | } |
| | |
| | | import com.alibaba.fastjson2.annotation.JSONField; |
| | | import com.alibaba.fastjson2.writer.ObjectWriterImplToString; |
| | | import com.baomidou.mybatisplus.annotation.IdType; |
| | | import com.baomidou.mybatisplus.annotation.TableField; |
| | | import com.baomidou.mybatisplus.annotation.TableId; |
| | | import com.baomidou.mybatisplus.annotation.TableName; |
| | | import com.dy.common.po.BaseEntity; |
| | |
| | | */ |
| | | @Schema(description = "删除标识", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | private Byte deleted; |
| | | |
| | | |
| | | ///////////////////////////////////////// |
| | | // 非数据库属性 |
| | | ///////////////////////////////////////// |
| | | @TableField(exist = false) |
| | | @Schema(description = "取水口编号") |
| | | public String intakeName ; |
| | | } |
| | |
| | | */ |
| | | public Byte powerType; |
| | | |
| | | /** |
| | | * 发送消息时刻 |
| | | */ |
| | | public Long sendMsTime ; |
| | | |
| | | public void valueFrom(DataV1_0_1 dV1_0_1, String rtuDt, DataAlarmVo alarmVo, DataStateVo stateVo) throws Exception{ |
| | | this.dt = DateTime.dateFrom_yyyy_MM_dd_HH_mm_ss(dV1_0_1.dt) ; |
| | | this.rtuDt = DateTime.dateFrom_yyyy_MM_dd_HH_mm_ss(rtuDt) ; |
| | |
| | | /** |
| | | * @Author: liurunyu |
| | | * @Date: 2024/7/24 17:09 |
| | | * @Description |
| | | * @Description 以用水户统计用水量 |
| | | */ |
| | | @Data |
| | | public class VoClientAmountStatistics { |
| | |
| | | /** |
| | | * @Author: liurunyu |
| | | * @Date: 2024/7/24 14:16 |
| | | * @Description 以取水口统计漏损 |
| | | * @Description 以取水口统计取水量 |
| | | */ |
| | | @Data |
| | | public class VoIntakeAmountStatistics { |
| | |
| | | auto-statistics: |
| | | startHour: 17 #开始小时 0 |
| | | startMinute: 19 #开始分钟 5 |
| | | |
| | | #钉钉消息推送 |
| | | dingtalk: |
| | | robot: |
| | | url: https://oapi.dingtalk.com/robot/send |
| | | access-token: fecef8e7725998f8912af05419580861aafc73413c4920036c07c050fa33055f |
| | | secret: SEC6042bc964d08899a5853eb321eb5a4d842a395982777f815bd07451c879228b7 |
| | | at-all: true |
| | | mobile: 18602657034 |
| | |
| | | </select> |
| | | |
| | | <!--根据控制器地址获取控制器列表--> |
| | | <select id="getControllersByRtuAddrAndIntakeNotNull" parameterType="java.lang.String" resultMap="PartResultMap"> |
| | | SELECT |
| | | <include refid="Part_Column_List"> |
| | | </include> |
| | | FROM pr_controller WHERE deleted = 0 AND intakeId is not null AND rtuAddr=#{rtuAddr,jdbcType=VARCHAR} |
| | | <select id="getControllersByRtuAddrAndIntakeNotNull" parameterType="java.lang.String" resultType="com.dy.pipIrrGlobal.pojoPr.PrController"> |
| | | SELECT tb.id id, |
| | | tb.rtuAddr rtuAddr, |
| | | tb.intakeId intakeId, |
| | | itb.name intakeName |
| | | FROM pr_controller tb |
| | | INNER JOIN pr_intake itb on tb.intakeId=itb.id |
| | | WHERE deleted = 0 AND intakeId is not null AND rtuAddr=#{rtuAddr,jdbcType=VARCHAR} |
| | | </select> |
| | | |
| | | <!--根据控制器编号逻辑删除控制--> |
| | |
| | | <result column="alarm_battery_volt" jdbcType="TINYINT" property="alarmBatteryVolt" /> |
| | | <result column="alarm_valve" jdbcType="TINYINT" property="alarmValve" /> |
| | | <result column="power_type" jdbcType="TINYINT" property="alarmValve" /> |
| | | <result column="send_ms_time" jdbcType="BIGINT" property="sendMsTime" /> |
| | | </resultMap> |
| | | <sql id="Base_Column_List"> |
| | | <!--@mbg.generated--> |
| | | id, controller_id, intake_id, rtu_addr, dt, rtu_dt, valve_state, alarm_remain_water, |
| | | alarm0_water_remain, alarm_exceed_year, alarm_water_meter_fault, alarm_loss, alarm_water_meter_break, |
| | | alarm_ele_meter_fault, alarm0_money_remain, alarm_inner_door, alarm_outer_door, alarm_ele_miss, |
| | | alarm_ele_exceed, alarm_ele_low_volt, state_ic_enable,alarm_battery_volt,alarm_valve,power_type |
| | | alarm_ele_exceed, alarm_ele_low_volt, state_ic_enable,alarm_battery_volt,alarm_valve,power_type,send_ms_time |
| | | </sql> |
| | | <select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="BaseResultMap"> |
| | | <!--@mbg.generated--> |
| | |
| | | alarm_loss, alarm_water_meter_break, alarm_ele_meter_fault, |
| | | alarm0_money_remain, alarm_inner_door, alarm_outer_door, |
| | | alarm_ele_miss, alarm_ele_exceed, alarm_ele_low_volt, |
| | | state_ic_enable,alarm_battery_volt,alarm_valve,power_type) |
| | | state_ic_enable,alarm_battery_volt,alarm_valve,power_type, |
| | | send_ms_time) |
| | | values (#{id,jdbcType=BIGINT}, #{controllerId,jdbcType=BIGINT}, #{intakeId,jdbcType=BIGINT}, |
| | | #{rtuAddr,jdbcType=VARCHAR}, #{dt,jdbcType=TIMESTAMP}, #{rtuDt,jdbcType=TIMESTAMP}, |
| | | #{valveState,jdbcType=TINYINT}, #{alarmRemainWater,jdbcType=TINYINT}, #{alarm0WaterRemain,jdbcType=TINYINT}, |
| | |
| | | #{alarm0MoneyRemain,jdbcType=TINYINT}, #{alarmInnerDoor,jdbcType=TINYINT}, #{alarmOuterDoor,jdbcType=TINYINT}, |
| | | #{alarmEleMiss,jdbcType=TINYINT}, #{alarmEleExceed,jdbcType=TINYINT}, #{alarmEleLowVolt,jdbcType=TINYINT}, |
| | | #{stateIcEnable,jdbcType=TINYINT}, #{alarmBatteryVolt,jdbcType=TINYINT}, #{alarmValve,jdbcType=TINYINT}, |
| | | #{powerType,jdbcType=TINYINT}) |
| | | #{powerType,jdbcType=TINYINT},#{sendMsTime,jdbcType=BIGINT}) |
| | | </insert> |
| | | <insert id="insertSelective" parameterType="com.dy.pipIrrGlobal.pojoRm.RmAlarmStateLast"> |
| | | <!--@mbg.generated--> |
| | |
| | | <if test="powerType != null"> |
| | | power_type, |
| | | </if> |
| | | <if test="sendMsTime != null"> |
| | | send_ms_time, |
| | | </if> |
| | | </trim> |
| | | <trim prefix="values (" suffix=")" suffixOverrides=","> |
| | | <if test="id != null"> |
| | |
| | | </if> |
| | | <if test="powerType != null"> |
| | | #{powerType,jdbcType=TINYINT}, |
| | | </if> |
| | | <if test="sendMsTime != null"> |
| | | #{sendMsTime,jdbcType=BIGINT}, |
| | | </if> |
| | | </trim> |
| | | </insert> |
| | |
| | | <if test="powerType != null"> |
| | | power_type = #{powerType,jdbcType=TINYINT}, |
| | | </if> |
| | | <if test="sendMsTime != null"> |
| | | send_ms_time = #{sendMsTime,jdbcType=BIGINT}, |
| | | </if> |
| | | </set> |
| | | where id = #{id,jdbcType=BIGINT} |
| | | </update> |
| | |
| | | state_ic_enable = #{stateIcEnable,jdbcType=TINYINT}, |
| | | alarm_battery_volt = #{alarmBatteryVolt,jdbcType=TINYINT}, |
| | | alarm_valve = #{alarmValve,jdbcType=TINYINT}, |
| | | power_type = #{powerType,jdbcType=TINYINT} |
| | | power_type = #{powerType,jdbcType=TINYINT}, |
| | | send_ms_time = #{powerType,jdbcType=BIGINT} |
| | | where id = #{id,jdbcType=BIGINT} |
| | | </update> |
| | | <!--根据指定条件获取记录总数--> |
| | |
| | | |
| | | //工作报太频繁,N次上报处理1次,取值范围是1-100 |
| | | ServerProperties.workReportDealOneByTimes = conf.getSetAttrPlusInt(doc, "config.base", "workReportDealOneByTimes", null, 1, 100, null) ; |
| | | if(ServerProperties.workReportDealOneByTimes < 1 || ServerProperties.workReportDealOneByTimes > 100){ |
| | | throw new Exception("workReportDealOneByTimes取值必须是1~100") ; |
| | | } |
| | | |
| | | //有报警发生时,向钉钉发送消息的间隔时长(分钟) |
| | | ServerProperties.sendDingDingAlarmMsInterval = conf.getSetAttrPlusInt(doc, "config.base", "sendDingDingAlarmMsInterval", null, 1, 600, null) ; |
| | | |
| | | //设置ID生成器的后缀 |
| | | IDLongGenerator.setSuffix(ServerProperties.dbDataIdSuffix.intValue()); |
| | |
| | | //工作报太频繁,N次上报处理1次 |
| | | public static Integer workReportDealOneByTimes = 5 ; |
| | | |
| | | //有报警发生时,向钉钉发送消息的间隔时长(分钟) |
| | | public static Integer sendDingDingAlarmMsInterval = 60 ; |
| | | |
| | | } |
| | |
| | | return instance ; |
| | | } |
| | | |
| | | |
| | | public static Integer[] info(){ |
| | | Integer comTotalDown = 0 ;//缓存的下行命令总数 |
| | | Integer comNoResTotalDownByOnLine = 0 ;//RTU在线,但对其下行命令未收到应答的总数 |
| | | Integer comNoResTotalDownByOffLine = 0 ;//RTU离线,但对其下行命令未收到应答的总数 |
| | | MidResultToRtu res ; |
| | | TcpDownCommandObj obj ; |
| | | Node node = cacheQueue.getFirstNode() ; |
| | | while(node != null && node.obj != null){ |
| | | obj = (TcpDownCommandObj)node.obj; |
| | | res = obj.result ; |
| | | if(!obj.onceReceivedResult){ |
| | | comTotalDown ++ ; |
| | | if(TcpSessionCache.isConnect(res.rtuAddr)){ |
| | | comNoResTotalDownByOnLine ++ ; |
| | | }else{ |
| | | comNoResTotalDownByOffLine ++ ; |
| | | } |
| | | } |
| | | } |
| | | return new Integer[]{comTotalDown, comNoResTotalDownByOnLine, comNoResTotalDownByOffLine} ; |
| | | } |
| | | |
| | | /** |
| | | * 缓存命令 |
| | | * @param result |
| | |
| | | */ |
| | | private static HashMap<String, TcpSession> sessionTable = new HashMap<String, TcpSession>() ; |
| | | |
| | | |
| | | /** |
| | | * 得到信息 |
| | | * @return |
| | | */ |
| | | public static Integer[] info(){ |
| | | Integer rtuTotalConnect = 0 ;//已经连接过中间件的RTU总数(包括在线与离线的) |
| | | Integer rtuTotalOnLine = 0 ;//在线RTU总数 |
| | | Integer rtuTotalOffLine = 0 ;//离线RTU总数 |
| | | synchronized (sessionTable){ |
| | | rtuTotalConnect = sessionTable.size() ; |
| | | Collection<TcpSession> col = sessionTable.values() ; |
| | | for(TcpSession se : col){ |
| | | if(se.ioSession.isConnected()){ |
| | | rtuTotalOnLine ++ ; |
| | | }else{ |
| | | rtuTotalOffLine ++ ; |
| | | } |
| | | } |
| | | } |
| | | return new Integer[] {rtuTotalConnect, rtuTotalOnLine, rtuTotalOffLine} ; |
| | | } |
| | | |
| | | /** |
| | | * 关闭所有网络连接 |
| | | */ |
| | |
| | | return this.stopTcpSv(com) ; |
| | | }else if(code.equals(CodeLocal.recoverTcpSv)){ |
| | | return this.recoverTcpSv(com) ; |
| | | }else if(code.equals(CodeLocal.mwState)){ |
| | | return this.mwInfo(com) ; |
| | | } |
| | | return ReturnCommand.errored("出错,收到内部命令的功能码不能识别!", com.getId(), com.getCode()) ; |
| | | } |
| | |
| | | |
| | | |
| | | |
| | | /** |
| | | * 查询通信中间件运行情况 |
| | | * @throws Exception |
| | | */ |
| | | private Command mwInfo(Command command) throws Exception{ |
| | | MwInfoVo mwInfo = new MwInfoDeal().deal() ; |
| | | return ReturnCommand.successed("查询通信中间件运行情况", command.getId(), command.getCode(), mwInfo) ; |
| | | } |
| | | |
| | | |
| | | } |
| | |
| | | public static final String allProtocols = "LCD0100" ;//查询所有协议配置 |
| | | |
| | | public static final String stopTcpSv = "LCD0110" ;//停止TCP服务,不再接入新的TCP连接,已经TCP连接的全部断连接 |
| | | |
| | | public static final String recoverTcpSv = "LCD0112" ;//重启TCP服务,接入新的TCP连接 |
| | | |
| | | public static final String mwState = "LCD0200" ;//得到通信中间件运行信息 |
| | | |
| | | } |
New file |
| | |
| | | package com.dy.rtuMw.server.local.localProtocol; |
| | | |
| | | import com.dy.common.threadPool.TreadPoolFactory; |
| | | import com.dy.rtuMw.server.forTcp.TcpDownCommandCache; |
| | | import com.dy.rtuMw.server.forTcp.TcpSessionCache; |
| | | import com.dy.rtuMw.server.rtuData.RtuDataCache; |
| | | import com.dy.rtuMw.server.rtuData.TaskPool; |
| | | |
| | | /** |
| | | * @Author: liurunyu |
| | | * @Date: 2024/7/29 11:07 |
| | | * @Description |
| | | */ |
| | | public class MwInfoDeal { |
| | | |
| | | public MwInfoVo deal(){ |
| | | MwInfoVo vo = new MwInfoVo() ; |
| | | Integer[] info = TcpSessionCache.info() ; |
| | | vo.rtuTotalConnect = info[0] ; |
| | | vo.rtuTotalOnLine = info[1] ; |
| | | vo.rtuTotalOffLine = info[2] ; |
| | | |
| | | info = TcpDownCommandCache.info() ; |
| | | vo.comTotalDown = info[0] ; |
| | | vo.comNoResTotalDownByOnLine = info[1] ; |
| | | vo.comNoResTotalDownByOffLine = info[2] ; |
| | | |
| | | vo.dataTotalUp = RtuDataCache.size() ; |
| | | |
| | | info = TreadPoolFactory.pool_short_state() ; |
| | | vo.shortCurThread = info[0] ; |
| | | vo.shortMaxThread = info[1] ; |
| | | vo.shortMinThread = info[2] ; |
| | | |
| | | info = TreadPoolFactory.pool_long_state() ; |
| | | vo.longCurThread = info[0] ; |
| | | vo.longMaxThread = info[1] ; |
| | | vo.longMinThread = info[2] ; |
| | | |
| | | vo.taskTreePoolTotalInstance = TaskPool.totalTasks() ; |
| | | |
| | | return vo ; |
| | | } |
| | | } |
New file |
| | |
| | | package com.dy.rtuMw.server.local.localProtocol; |
| | | |
| | | import lombok.Data; |
| | | |
| | | /** |
| | | * @Author: liurunyu |
| | | * @Date: 2024/7/29 10:54 |
| | | * @Description |
| | | */ |
| | | @Data |
| | | public class MwInfoVo { |
| | | public Integer rtuTotalConnect ;//已经连接过中间件的RTU总数(包括在线与离线的) |
| | | public Integer rtuTotalOnLine ;//在线RTU总数 |
| | | public Integer rtuTotalOffLine ;//离线RTU总数 |
| | | |
| | | public Integer comTotalDown ;//缓存的下行命令总数 |
| | | public Integer comNoResTotalDownByOnLine;//RTU在线,但对其下行命令未收到应答的总数 |
| | | public Integer comNoResTotalDownByOffLine;//RTU离线,但对其下行命令未收到应答的总数 |
| | | |
| | | public Integer dataTotalUp ;//上行数据在缓存中还未处理的总数 |
| | | |
| | | public Integer shortCurThread = 0 ;//短线程池当前线程数 |
| | | public Integer shortMaxThread = 0 ;//短线程池最大线程数 |
| | | public Integer shortMinThread = 0 ;//短线程池最小线程数 |
| | | public Integer longCurThread = 0 ;//长线程池当前线程数 |
| | | public Integer longMaxThread = 0 ;//长线程池最大线程数 |
| | | public Integer longMinThread = 0 ;//长线程池最小线程数 |
| | | |
| | | public Integer taskTreePoolTotalInstance = 0 ;//任务树池任务实例总数 |
| | | |
| | | public String toString(){ |
| | | StringBuilder sb = new StringBuilder() ; |
| | | sb.append("通信中间件运行信息:\n"); |
| | | sb.append(" 连接RTU总数:" + rtuTotalConnect + "\n"); |
| | | sb.append(" 在线RTU总数:" + rtuTotalOnLine + "\n"); |
| | | sb.append(" 离线RTU总数:" + rtuTotalOffLine + "\n"); |
| | | sb.append(" 下行未应答命令总数:" + comTotalDown + "\n"); |
| | | sb.append(" 在线RTU未应答命令总数:" + comNoResTotalDownByOnLine + "\n"); |
| | | sb.append(" 离线RTU未应答命令总数:" + comNoResTotalDownByOffLine + "\n"); |
| | | sb.append(" 上行未处理数据总数:" + dataTotalUp + "\n"); |
| | | sb.append(" 短线程池当前线程数:" + shortCurThread + "\n"); |
| | | sb.append(" 短线程池配置最大线程数:" + shortMaxThread + "\n"); |
| | | sb.append(" 短线程池配置最小线程数:" + shortMinThread + "\n"); |
| | | sb.append(" 长线程池当前线程数:" + longCurThread + "\n"); |
| | | sb.append(" 长线程池配置最大线程数:" + longMaxThread + "\n"); |
| | | sb.append(" 长线程池配置最小线程数:" + longMinThread + "\n"); |
| | | sb.append(" 任务树池任务实例总数:" + taskTreePoolTotalInstance + "\n"); |
| | | sb.append("\n"); |
| | | |
| | | return sb.toString() ; |
| | | } |
| | | } |
| | |
| | | private static Logger log = LogManager.getLogger(TaskPool.class.getName()) ; |
| | | |
| | | private static List<TaskSurpport> tasks = new ArrayList<TaskSurpport>() ; |
| | | |
| | | private static Integer taskTotal = 0 ; |
| | | |
| | | private static TreeConfig taskTreeConf ; |
| | | |
| | | |
| | | public static void setTaskTreeCofig(TreeConfig conf){ |
| | | taskTreeConf = conf ; |
| | | } |
| | | |
| | | /** |
| | | * 得到任务树实例总数 |
| | | * @return |
| | | */ |
| | | public static Integer totalTasks() { |
| | | return taskTotal ; |
| | | } |
| | | |
| | | |
| | |
| | | } finally { |
| | | if(t == null){ |
| | | log.error("实例化上行数据处理任务对象失败!" ); |
| | | }else{ |
| | | taskTotal++ ; |
| | | } |
| | | } |
| | | } |
| | |
| | | import com.dy.common.mw.protocol.p206V1_0_0.upVos.*; |
| | | import com.dy.common.util.DateTime; |
| | | import com.dy.pipIrrGlobal.pojoRm.RmAlarmStateHistory; |
| | | import com.dy.rtuMw.server.ServerProperties; |
| | | import com.dy.rtuMw.server.rtuData.TaskSurpport; |
| | | import com.dy.rtuMw.server.rtuData.dbSv.DbSv; |
| | | import com.dy.common.mw.protocol.Data; |
| | |
| | | po.intakeId = controller==null?null:controller.getIntakeId() ; |
| | | po.rtuAddr = rtuAddr ; |
| | | po.valueFrom(dV1_0_1, rtuDt, alarmVo, stateVo); |
| | | if(alarmVo.hasAlarm()){ |
| | | po.sendMsTime = System.currentTimeMillis() ; |
| | | this.sendMessage(controller, alarmVo); |
| | | } |
| | | sv.saveRmAlarmStateLast(po) ; |
| | | }else{ |
| | | if(po.sendMsTime == null){ |
| | | po.sendMsTime = System.currentTimeMillis() ; |
| | | this.sendMessage(controller, alarmVo); |
| | | }else{ |
| | | Long now = System.currentTimeMillis() ; |
| | | if(((now - po.sendMsTime) / (1000 * 60)) > ServerProperties.sendDingDingAlarmMsInterval){ |
| | | //大于规定的间隔时间 |
| | | po.sendMsTime = System.currentTimeMillis() ; |
| | | this.sendMessage(controller, alarmVo); |
| | | } |
| | | } |
| | | po = this.update(controller, po, rtuDt, dV1_0_1, alarmVo, stateVo) ; |
| | | sv.updateRmAlarmStateLast(po); |
| | | } |
| | |
| | | |
| | | |
| | | /** |
| | | * 虚拟卡在取水中的占用状态改为非应用状态 |
| | | * 虚拟卡在取水口上的占用状态改为非应用状态 |
| | | */ |
| | | private void updateVirCardNoUseState(DbSv sv, |
| | | PrController controller, |
| | |
| | | |
| | | } |
| | | |
| | | private void sendMessage(PrController controller, DataAlarmVo alarmVo){ |
| | | String ms = "取水口" + controller.getIntakeName() + "产生报警:" + alarmVo.alarmContent() ; |
| | | } |
| | | |
| | | } |
| | |
| | | package com.dy.rtuMw.server.rtuData.p206V1_0_0; |
| | | |
| | | |
| | | import com.dy.common.mw.protocol.p206V1_0_0.DataV1_0_1; |
| | | import com.dy.common.mw.protocol.p206V1_0_0.upVos.DataCd02Vo; |
| | | import com.dy.rtuMw.server.rtuData.TaskSurpport; |
| | | import com.dy.common.mw.protocol.Data; |
| | | import com.dy.common.mw.protocol.p206V1_0_0.ProtocolConstantV206V1_0_0; |
| | |
| | | onceUpDataRtus.put(rtuAddr, true) ; |
| | | } |
| | | |
| | | DbSv sv = (DbSv)SpringContextUtil.getBean(DbSv.class) ; |
| | | DbSv sv = SpringContextUtil.getBean(DbSv.class) ; |
| | | if(sv != null){ |
| | | PrController controller = sv.getControllersByRtuAddrAndIntakeNotNull(rtuAddr) ; |
| | | PrControllerTramp controllerTramp = null ; |
| | |
| | | cacheUpDownDataMaxCount:上下行数据缓存队列中缓存数据个数的最大值,这个与现实项目所接水表数相关 |
| | | disconnectedByNoUpDataMinutes:没有上行数据的分钟数,达到这个分钟数,认为RTU断网了,取值范围是2-100 |
| | | workReportDealOneByTimes: 工作报太频繁,N次上报处理1次,取值范围是1-100 |
| | | sendDingDingAlarmMsInterval: 有报警发生时,向钉钉发送消息的间隔时长(分钟) |
| | | --> |
| | | <base |
| | | orgTag="ym" |
| | |
| | | cacheUpDownDataMaxCount="110000" |
| | | disconnectedByNoUpDataMinutes="3" |
| | | workReportDealOneByTimes="5" |
| | | sendDingDingAlarmMsInterval="60" |
| | | /> |
| | | |
| | | <!-- |
| | |
| | | |
| | | <base rtuAddr="532328059995" onlyOneHeartBeat="true" icCardAddr="3B7D1E1A" icCardNo="61181622830147821"></base> |
| | | <!-- --> |
| | | <tcpCl mwServerIp="192.168.40.182" mwServerPort="60000" connectTimeout="3000" /> |
| | | <tcpCl mwServerIp="127.0.0.1" mwServerPort="60000" connectTimeout="3000" /> |
| | | </config> |
| | |
| | | public static final String allProtocols = "LCD0100" ;//查询所有协议配置 |
| | | |
| | | public static final String stopTcpSv = "LCD0110" ;//停止TCP服务,不再接入新的TCP连接,已经TCP连接的全部断连接 |
| | | |
| | | public static final String recoverTcpSv = "LCD0112" ;//恢复TCP服务,接入新的TCP连接 |
| | | |
| | | public static final String mwState = "LCD0200" ;//得到通信中间件运行信息 |
| | | |
| | | } |
| | |
| | | rt = this.stopTcpSv() ; |
| | | }else if(com.equals(CodeLocal.recoverTcpSv)){ |
| | | rt = this.recoverTcpSv() ; |
| | | }else if(com.equals(CodeLocal.mwState)){ |
| | | rt = this.mwState() ; |
| | | }else if(com.equals("10")){ |
| | | rt = this.cd10() ; |
| | | }else if(com.equals("21")){ |
| | |
| | | return this.sendCom2Mw(this.commandLocal(CodeLocal.recoverTcpSv, null, null)) ; |
| | | } |
| | | |
| | | private BaseResponse mwState(){ |
| | | return this.sendCom2Mw(this.commandLocal(CodeLocal.mwState, null, null)) ; |
| | | } |
| | | |
| | | private BaseResponse cd10(){ |
| | | Com10Vo comVo = new Com10Vo() ; |
| | | comVo.rtuAddr = "532328059995" ;//前6位是行政区划码,后6位是序列号最大是065535 |
| | |
| | | import com.dy.pipIrrGlobal.voSe.VoActiveCard; |
| | | import com.dy.pipIrrProject.intake.qo.OnLineIntakesQO; |
| | | import com.dy.pipIrrProject.result.ProjectResultCode; |
| | | import com.taobao.api.ApiException; |
| | | import io.swagger.v3.oas.annotations.Operation; |
| | | import io.swagger.v3.oas.annotations.Parameter; |
| | | import io.swagger.v3.oas.annotations.media.Content; |
| | |
| | | @RequiredArgsConstructor |
| | | public class IntakeCtrl { |
| | | private final IntakeSv intakeSv; |
| | | |
| | | @GetMapping("/test") |
| | | public String sendMessage(String message) throws ApiException { |
| | | return intakeSv.sendMessage(message); |
| | | } |
| | | |
| | | /** |
| | | * 客户端请求得到所有取水口名字 |
| | |
| | | @PostMapping(path = "add", consumes = MediaType.APPLICATION_JSON_VALUE) |
| | | @Transactional(rollbackFor = Exception.class) |
| | | @SsoAop() |
| | | public BaseResponse<Boolean> add(@RequestBody @Valid PrIntake po, @Parameter(hidden = true) BindingResult bindingResult) { |
| | | public BaseResponse<Boolean> add(@RequestBody @Valid PrIntake po, @Parameter(hidden = true) BindingResult bindingResult) { |
| | | DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); |
| | | if (bindingResult != null && bindingResult.hasErrors()) { |
| | | return BaseResponseUtils.buildFail(Objects.requireNonNull(bindingResult.getFieldError()).getDefaultMessage()); |
| | |
| | | return BaseResponseUtils.buildFail(ProjectResultCode.INTAKE_NAME_EXIST.getMessage()); |
| | | } |
| | | po.setOperateDt(new Date()); |
| | | po.setDeleted((byte)0); |
| | | po.setDeleted((byte) 0); |
| | | Integer rec = Optional.ofNullable(intakeSv.addIntake(po)).orElse(0); |
| | | if (rec == 0) { |
| | | return BaseResponseUtils.buildFail(ProjectResultCode.ADD_INTAKE_FAIL.getMessage()); |
| | |
| | | return BaseResponseUtils.buildFail(Objects.requireNonNull(bindingResult.getFieldError()).getDefaultMessage()); |
| | | } |
| | | List<Long> ids = intakeSv.getIntakeIdByNameExcludeId(po.getId(), po.getName()); |
| | | if (ids.size() > 0){ |
| | | if (ids.size() > 0) { |
| | | return BaseResponseUtils.buildFail(ProjectResultCode.INTAKE_NAME_EXIST.getMessage()); |
| | | } |
| | | int count; |
| | | po.setOperateDt( new Date()); |
| | | po.setOperateDt(new Date()); |
| | | try { |
| | | count = this.intakeSv.update(po); |
| | | } catch (Exception e) { |
| | |
| | | |
| | | /** |
| | | * 获取取水口列表(在线和不在线) |
| | | * |
| | | * @param qo |
| | | * @return |
| | | */ |
| | |
| | | |
| | | /** |
| | | * 根据操作员获取常用取水口(在线和不在线) |
| | | * |
| | | * @param operator |
| | | * @return |
| | | */ |
| | |
| | | import com.alibaba.fastjson2.JSON; |
| | | import com.alibaba.fastjson2.JSONArray; |
| | | import com.alibaba.fastjson2.JSONObject; |
| | | import com.dy.common.multiDataSource.DataSourceContext; |
| | | import com.dy.common.mw.protocol.Command; |
| | | import com.dy.common.webUtil.BaseResponse; |
| | | import com.dy.common.webUtil.QueryResultVo; |
| | | import com.dy.pipIrrGlobal.config.DingTalk; |
| | | import com.dy.pipIrrGlobal.daoPr.PrDivideMapper; |
| | | import com.dy.pipIrrGlobal.daoPr.PrIntakeMapper; |
| | | import com.dy.pipIrrGlobal.pojoPr.PrIntake; |
| | |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.apache.dubbo.common.utils.PojoUtils; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.core.env.Environment; |
| | | import org.springframework.http.HttpEntity; |
| | | import org.springframework.http.HttpHeaders; |
| | | import org.springframework.http.HttpMethod; |
| | |
| | | @Autowired |
| | | private RestTemplate restTemplate; |
| | | |
| | | protected static String mwUrlSendCom = "http://127.0.0.1:8070/rtuMw/com/send" ; |
| | | protected String comSendUrl; |
| | | |
| | | /** |
| | | * pro_mw:属性 |
| | | * tag从控制器中获取 |
| | | * key_mw:url的key |
| | | */ |
| | | private Environment env = null; |
| | | private String pro_mw = "mw"; |
| | | private String key_mw = "comSendUrl"; |
| | | @Autowired |
| | | public IntakeSv(Environment env) { |
| | | this.env = env; |
| | | } |
| | | |
| | | @Autowired |
| | | private DingTalk dingTalk; |
| | | |
| | | public String sendMessage(String message) { |
| | | try { |
| | | dingTalk.sendMessage(message); |
| | | } catch (Exception e) { |
| | | return "发送失败"; |
| | | } |
| | | return "发送成功"; |
| | | } |
| | | |
| | | /** |
| | | * 添加取水口 |
| | |
| | | public Long getSupperByVillageId(long vaId) { |
| | | return prIntakeMapper.getSupperByVillageId(vaId); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 保存修改实体 |
| | |
| | | com.id = Command.defaultId; |
| | | com.code = "LCD0001"; |
| | | com.type = "innerCommand"; |
| | | comSendUrl = env.getProperty(pro_mw + "." + DataSourceContext.get() + "." + key_mw); |
| | | |
| | | JSONObject response = (JSONObject) JSON.toJSON(sendCom2Mw(com)); |
| | | |
| | | if(response != null && response.getString("code").equals("0001")) { |
| | | JSONObject attachment = response.getJSONObject("content").getJSONObject("attachment").getJSONObject("onLineMap"); |
| | | HashMap<String, Boolean> onLineMap = JSON.parseObject(attachment.toJSONString(), HashMap.class); |
| | |
| | | * @return |
| | | */ |
| | | protected BaseResponse sendCom2Mw(Command com){ |
| | | String url = UriComponentsBuilder.fromUriString(mwUrlSendCom) |
| | | String url = UriComponentsBuilder.fromUriString(comSendUrl) |
| | | .build() |
| | | .toUriString(); |
| | | HttpHeaders headers = new HttpHeaders(); |
| | |
| | | #GenerateIdSetSuffixListener中应用,取值范围是0-99 |
| | | idSuffix: ${pipIrr.project.idSuffix} |
| | | #ConfigListener中应用 |
| | | #configFileNames: config-global.xml,config-demo.xml |
| | | #configFileNames: config-global.xml,config-demo.xml |
| | |
| | | #GenerateIdSetSuffixListener中应用,取值范围是0-99 |
| | | idSuffix: ${pipIrr.remote.idSuffix} |
| | | #ConfigListener中应用 |
| | | #configFileNames: config-global.xml,config-demo.xml |
| | | #configFileNames: config-global.xml,config-demo.xml |