Commit 3a29e559 authored by xukaiqiang's avatar xukaiqiang

init

parents
# Compiled class file
*.class
# Log file
*.log
# BlueJ files
*.ctxt
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
.idea
*.iml
*.settings
*.classpath
*.project
*.springBeans
*.factorypath
target
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>YeeAmosIec104IntfRoot</artifactId>
<groupId>com.yeejoin.amos</groupId>
<version>1.0.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>YeeAmosConnectCommon</artifactId>
</project>
\ No newline at end of file
package com.yeejoin.amos.fas.core.common.request;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
/**
*
* <pre>
* 分页实体
* </pre>
*
* @author as-chenjiajun
* @version $Id: CommonPageable.java, v 0.1 2016-12-14 上午10:42:44 as-chenjiajun
* Exp $
*/
public class CommonPageable implements Pageable {
/**
* 页号(大于等于0)
*/
protected int pageNumber = 0;
/**
* 每页大小(大于等于0)
*/
protected int pageSize = 10;
/**
* 起始索引
*/
protected int offset = 0;
/**
* 排序
*/
protected Sort sort = null;
public CommonPageable() {
this.pageNumber = 0;
this.pageSize = 10;
this.offset = pageSize * pageNumber;
}
public CommonPageable(int pageNumber, int pageSize) {
this.pageNumber = pageNumber;
this.pageSize = pageSize;
this.offset = pageSize * pageNumber;
}
public CommonPageable(int pageNumber, int pageSize, Sort sort) {
this.pageNumber = pageNumber;
this.pageSize = pageSize;
this.sort = sort;
this.offset = pageSize * pageNumber;
}
public int getPageNumber() {
return this.pageNumber;
}
public int getPageSize() {
return pageSize;
}
public int getOffset() {
offset = pageSize * pageNumber;
return offset;
}
public Sort getSort() {
return sort;
}
public Pageable next() {
return null;
}
public Pageable previousOrFirst() {
return null;
}
public Pageable first() {
return null;
}
public boolean hasPrevious() {
return false;
}
public void setPageNumber(int pageNumber) {
this.pageNumber = pageNumber;
}
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
public void setSort(Sort sort) {
this.sort = sort;
}
public void setOffset(int offset) {
this.offset = offset;
}
}
package com.yeejoin.amos.fas.core.common.request;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
/**
*
* <pre>
* 公共请求对象
* </pre>
*
* @author as-shibaobao
* @version $Id: CommonRequest.java, v 0.1 2018年1月26日 上午10:59:19 as-shibaobao Exp $
*/
@ApiModel
public class CommonRequest {
/**
* 字段名称
*/
@ApiModelProperty(value="字段名称",required=true)
private String name;
/**
* 字段值
*/
@ApiModelProperty(value="字段值",required=true)
private Object value;
/**
* 查询类型
*/
@ApiModelProperty(value="查询类型",notes="空值时,默认为等于;其它类型按QueryOperatorEnum",required=false)
private String type;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Object getValue() {
return value;
}
public void setValue(Object value) {
this.value = value;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}
/**
* NewHeight.com Inc.
* Copyright (c) 2008-2010 All Rights Reserved.
*/
package com.yeejoin.amos.fas.core.common.response;
import java.util.List;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
/**
* <pre>
* 分页数据
* </pre>
*
* @author as-youjun
* @version $Id: CompanyPage.java, v 0.1 2017年4月13日 上午11:35:25 as-youjun Exp $
*/
public final class CommonPage<T> extends PageImpl<T> {
/**
* <pre>
* uid
* </pre>
*/
private static final long serialVersionUID = -5533124806408380886L;
/**
*
*/
private String message;
/**
* 返回结果状态
*/
private String result;
public CommonPage(List<T> content, Pageable pageable, long total) {
super(content, pageable, total);
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public String getResult()
{
return result;
}
public void setResult(String result)
{
this.result = result;
}
}
package com.yeejoin.amos.connect.dao;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.NoRepositoryBean;
import org.springframework.data.repository.PagingAndSortingRepository;
import java.io.Serializable;
import java.util.List;
/**
* 基础dao
*
* @param <T>
* @param <ID>
*/
@NoRepositoryBean
public interface BaseDao<T, ID extends Serializable> extends JpaRepository<T, ID>, CrudRepository<T, ID>,
PagingAndSortingRepository<T, ID>, JpaSpecificationExecutor<T> {
public default T getOneBySpecification(Specification<T> specification) {
List<T> list = findAll(specification);
if (list.isEmpty()) {
return null;
} else {
return list.get(0);
}
}
}
package com.yeejoin.amos.connect.dao.entity;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import javax.persistence.*;
import java.io.Serializable;
import java.util.Date;
/**
* <pre>
* 基本实体类
* </pre>
*
*/
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public class BasicEntity implements Serializable{
private static final long serialVersionUID = -5464322936854328207L;
/**
* id
*/
private long id;
@CreatedDate
@Column(name="create_date")
private Date createDate;
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column(name = "ID",nullable=false,unique=true)
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public Date getCreateDate() {
return createDate;
}
public void setCreateDate(Date createDate) {
this.createDate = createDate;
}
}
package com.yeejoin.amos.connect.dao.entity;
import javax.persistence.*;
@Entity
@Table(name="i_client_linsten")
public class ClientListenVo {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column(name = "ID",nullable=false,unique=true)
private Long id;
private String url;
private String remark;
private String channleNo;
private String dataType;
private String name;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getRemark() {
return remark;
}
public void setRemark(String remark) {
this.remark = remark;
}
public String getChannleNo() {
return channleNo;
}
public void setChannleNo(String channleNo) {
this.channleNo = channleNo;
}
public String getDataType() {
return dataType;
}
public void setDataType(String dataType) {
this.dataType = dataType;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
package com.yeejoin.amos.connect.dao.entity;
import javax.persistence.*;
import java.util.Date;
@Entity
@Table(name="i_ip_port_conf")
public class ConfigVo {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column(name = "ID",nullable=false,unique=true)
private Long id;
private String ip;
private String port;
private String commonAddress;
private String serviceType;
private String serviceId;
private String channelNo;
private int isDelete;
private Date lastUpdateTime;
private String name;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getIp() {
return ip;
}
public void setIp(String ip) {
this.ip = ip;
}
public String getPort() {
return port;
}
public void setPort(String port) {
this.port = port;
}
public String getServiceType() {
return serviceType;
}
public void setServiceType(String serviceType) {
this.serviceType = serviceType;
}
public int getIsDelete() {
return isDelete;
}
public void setIsDelete(int isDelete) {
this.isDelete = isDelete;
}
public Date getLastUpdateTime() {
return lastUpdateTime;
}
public void setLastUpdateTime(Date lastUpdateTime) {
this.lastUpdateTime = lastUpdateTime;
}
public String getCommonAddress() {
return commonAddress;
}
public void setCommonAddress(String commonAddress) {
this.commonAddress = commonAddress;
}
public String getServiceId() {
return serviceId;
}
public void setServiceId(String serviceId) {
this.serviceId = serviceId;
}
public String getChannelNo() {
return channelNo;
}
public void setChannelNo(String channelNo) {
this.channelNo = channelNo;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
package com.yeejoin.amos.connect.dao.entity;
import com.yeejoin.amos.connect.utils.ExcelColumn;
import javax.persistence.*;
import java.io.Serializable;
@Entity
@Table(name="i_point_config")
public class PointConfigVo implements Serializable{
/**
*
*/
private static final long serialVersionUID = -7259637704136034266L;
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column(name = "ID",nullable=false,unique=true)
private Long id;
private Long commonAddress;
@ExcelColumn(value = "信息地址", col = 1)
private Integer originatorAddress;
private String value;
@ExcelColumn(value = "点名称", col = 2)
private String name;
@ExcelColumn(value = "点分类", col = 3)
private String pointClassify;
@ExcelColumn(value = "点编码", col = 4)
private String pointCode;
@ExcelColumn(value = "说明", col = 5)
private String remark;
@ExcelColumn(value = "是否有效", col = 6)
private boolean invalid;
private String channelNo;
private String pointType;
public PointConfigVo() {};
public PointConfigVo(Long id, Long commonAddress, Integer originatorAddress, String pointType, String pointClassify, boolean invalid, String channelNo, String name, String pointCode ) {
super();
this.id = id;
this.commonAddress = commonAddress;
this.originatorAddress = originatorAddress;
this.name = name;
this.pointClassify = pointClassify;
this.pointCode = pointCode;
this.invalid = invalid;
this.channelNo = channelNo;
this.pointType = pointType;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Long getCommonAddress() {
return commonAddress;
}
public void setCommonAddress(Long commonAddress) {
this.commonAddress = commonAddress;
}
public Integer getOriginatorAddress() {
return originatorAddress;
}
public void setOriginatorAddress(Integer originatorAddress) {
this.originatorAddress = originatorAddress;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getRemark() {
return remark;
}
public void setRemark(String remark) {
this.remark = remark;
}
public boolean getInvalid() {
return invalid;
}
public void setInvalid(boolean invalid) {
this.invalid = invalid;
}
public String getChannelNo() {
return channelNo;
}
public void setChannelNo(String channelNo) {
this.channelNo = channelNo;
}
public String getPointCode() {
return pointCode;
}
public void setPointCode(String pointCode) {
this.pointCode = pointCode;
}
public String getPointType() {
return pointType;
}
public void setPointType(String pointType) {
this.pointType = pointType;
}
public String getPointClassify() {
return pointClassify;
}
public void setPointClassify(String pointClassify) {
this.pointClassify = pointClassify;
}
@Override
public String toString() {
return "PointConfigVo [id=" + id + ", commonAddress=" + commonAddress + ", originatorAddress="
+ originatorAddress + ", value=" + value + ", name=" + name + ", pointClassify=" + pointClassify
+ ", pointCode=" + pointCode + ", remark=" + remark + ", invalid=" + invalid + ", channelNo="
+ channelNo + ", pointType=" + pointType + "]";
}
}
package com.yeejoin.amos.connect.dao.entity;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name="i_transmit_mapper")
public class TransmitMapper {
@Id
@GeneratedValue(strategy= GenerationType.AUTO)
@Column(name = "ID",nullable=false,unique=true)
private Long id;
// @Column(columnDefinition = "comment '映射类型(UART,IEC104)'")
private String mapperType;
// @Column(columnDefinition = "comment '转发接收方地址(IP)'")
private String transmitIp;
// @Column(columnDefinition = "comment '转发接收方端口号'")
private String transmitPort;
// @Column(columnDefinition = "comment '转发方式(TCP,UDP,HTTP)'")
private String transmitType;
// @Column(columnDefinition = "comment '转发地址'")
private String transmitUrl;
// @Column(columnDefinition = "comment '映射ID'")
private Long mapperId;
public Long getId() {
return id;
}
public String getMapperType() {
return mapperType;
}
public String getTransmitIp() {
return transmitIp;
}
public String getTransmitPort() {
return transmitPort;
}
public String getTransmitType() {
return transmitType;
}
public String getTransmitUrl() {
return transmitUrl;
}
public Long getMapperId() {
return mapperId;
}
public void setId(Long id) {
this.id = id;
}
public void setMapperType(String mapperType) {
this.mapperType = mapperType;
}
public void setTransmitIp(String transmitIp) {
this.transmitIp = transmitIp;
}
public void setTransmitPort(String transmitPort) {
this.transmitPort = transmitPort;
}
public void setTransmitType(String transmitType) {
this.transmitType = transmitType;
}
public void setTransmitUrl(String transmitUrl) {
this.transmitUrl = transmitUrl;
}
public void setMapperId(Long mapperId) {
this.mapperId = mapperId;
}
}
package com.yeejoin.amos.connect.dao.entity;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import java.util.Date;
@Entity
@Table(name="i_uart_config")
public class UartVo {
@Id
@GeneratedValue(strategy= GenerationType.AUTO)
@Column(name = "ID",nullable=false,unique=true)
private Long id;
private String name;
private String remark;
private String createBy;
private Date createdTime;
private String serialPort;
private int baudRate;
private int dataBits;
private int stopBits;
private int parity;
private int isDelete;
public void setId(Long id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public void setRemark(String remark) {
this.remark = remark;
}
public void setCreateBy(String createBy) {
this.createBy = createBy;
}
public void setCreatedTime(Date createdTime) {
this.createdTime = createdTime;
}
public void setSerialPort(String serialPort) {
this.serialPort = serialPort;
}
public void setBaudRate(int baudRate) {
this.baudRate = baudRate;
}
public void setDataBits(int dataBits) {
this.dataBits = dataBits;
}
public void setStopBits(int stopBits) {
this.stopBits = stopBits;
}
public void setParity(int parity) {
this.parity = parity;
}
public void setIsDelete(int isDelete) {
this.isDelete = isDelete;
}
public Long getId() {
return id;
}
public String getName() {
return name;
}
public String getRemark() {
return remark;
}
public String getCreateBy() {
return createBy;
}
public Date getCreatedTime() {
return createdTime;
}
public int getBaudRate() {
return baudRate;
}
public int getDataBits() {
return dataBits;
}
public int getStopBits() {
return stopBits;
}
public int getParity() {
return parity;
}
public int getIsDelete() {
return isDelete;
}
public String getSerialPort() {
return serialPort;
}
}
package com.yeejoin.amos.connect.utils;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ExcelColumn {
/**
* Excel标题
*
* @return
* @author Lynch
*/
String value() default "";
/**
* Excel从左往右排列位置
*
* @return
* @author Lynch
*/
int col() default 0;
}
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>YeeAmosConnectStart</artifactId>
<name>YeeAmosConnectStart</name>
<parent>
<groupId>com.yeejoin.amos</groupId>
<artifactId>YeeAmosConnectRoot</artifactId>
<version>1.0.0</version>
</parent>
<dependencies>
<!-- 业务模块jar -->
<dependency>
<groupId>com.yeejoin.amos</groupId>
<artifactId>YeeAmosConnentCommon</artifactId>
<version>${iec104.version}</version>
</dependency>
<dependency>
<groupId>com.yeejoin.amos</groupId>
<artifactId>YeeAmosIec104IntfServer</artifactId>
<version>${iec104.version}</version>
</dependency>
<dependency>
<groupId>com.yeejoin.amos</groupId>
<artifactId>YeeAmosUartServer</artifactId>
<version>${iec104.version}</version>
</dependency>
</dependencies>
<!-- maven打包时将lib提取到jar同目录,将配置文件提取到jar目录/config/下 -->
<build>
<resources>
<!-- 先指定 src/main/resources下所有文件及文件夹为资源文件 -->
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*</include>
</includes>
<!-- 过滤不需要引用的文件 -->
<excludes>
<exclude>package.xml</exclude>
</excludes>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<!-- 添加index则不从mainfest中读取classpath,而是从Index.list中读取 -->
<!-- <index>true</index> -->
<manifest>
<mainClass>com.yeejoin.amos.YeeAmosIec104IntfStart</mainClass>
<!-- to create a class path to your dependecies you have to fill true
in this field -->
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<!--<classpathLayoutType>custom</classpathLayoutType> <customClasspathLayout>
lib/ artifact.groupId. {artifact.artifactId}.$${artifact.extension} </customClasspathLayout> -->
</manifest>
<manifestEntries>
<Class-Path>./</Class-Path>
</manifestEntries>
</archive>
<!-- <excludes> <exclude>config/**</exclude> </excludes> -->
<includes>
<include>**/**.class</include>
</includes>
</configuration>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<!-- not append assembly id in release file name -->
<appendAssemblyId>false</appendAssemblyId>
<descriptors>
<descriptor>src/main/resources/package.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
\ No newline at end of file
package com.yeejoin.amos;
import java.io.IOException;
import java.net.URISyntaxException;
import org.springframework.beans.BeansException;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.feign.EnableFeignClients;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Bean;
import org.springframework.core.annotation.Order;
import org.springframework.core.env.Environment;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import com.yeejoin.amos.iec104.context.FireAutoIntfContext;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
/**
* amosfireAutoIntf启动类
*
* @author as-gaodongdong
*/
@SpringBootApplication
@EnableTransactionManagement
@EnableConfigurationProperties
@EnableSwagger2
@ServletComponentScan
@EnableDiscoveryClient
@EnableFeignClients
@EnableHystrix
@EnableScheduling
public class YeeAmosIec104IntfStart implements ApplicationContextAware {
/**
* 启动FireAutoIntf-server
*
* @param args
* @throws IOException
* @throws URISyntaxException
*/
public static void main(String[] args) {
System.out.println("FireAutoIntf server starting...");
try {
SpringApplication application = new SpringApplication(
YeeAmosIec104IntfStart.class);
Environment environment = application.run(args).getEnvironment();
System.out.println("FireAutoIntf server is running...");
System.out.println("SwaggerUI: http://localhost:"
+ environment.getProperty("server.port")
+ "/swagger-ui.html");
} catch (Exception e) {
System.out.println("error occur when run FireAutoIntf server! " + e);
}
}
/**
* 获取并缓存上下文
*/
@Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
// 1.缓存spring上下文
FireAutoIntfContext.getInstance().setApplicationContext(applicationContext);
}
/**
* 跨域过滤器
*
* @return
*/
@Bean
@Order(0)
public CorsFilter corsFilter() {
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
final CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);// 允许cookies跨域
config.addAllowedOrigin("*");// #允许向该服务器提交请求的URI,*表示全部允许,在SpringMVC中,如果设成*,会自动转成当前请求头中的Origin
config.addAllowedHeader("*");// #允许访问的头信息,*表示全部
config.setMaxAge(3600L);// 预检请求的缓存时间(秒),即在这个时间段里,对于相同的跨域请求不会再预检了
config.addAllowedMethod("OPTIONS");
config.addAllowedMethod("HEAD");
config.addAllowedMethod("GET");
config.addAllowedMethod("PUT");
config.addAllowedMethod("POST");
config.addAllowedMethod("DELETE");
config.addAllowedMethod("PATCH");
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
}
\ No newline at end of file
package com.yeejoin.amos.filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;
import org.springframework.core.annotation.Order;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.stereotype.Component;
/**
* <pre>
* 跨域处理
* </pre>
*
* @author SmartRay
* @version CrossDomainFilter.java v0.1
* @time 2016-9-7 9:48:10
*/
@Component(value = "crossDomainFilter")
@EnableScheduling
@Order(0)
public class CrossDomainFilter implements Filter
{
public void destroy()
{
}
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain) throws IOException, ServletException
{
HttpServletResponse response = (HttpServletResponse) res;
// 允许所有域进行访问
response.setHeader("Access-Control-Allow-Origin", "*");
// 允许的方法
response.setHeader("Access-Control-Allow-Methods","GET,POST,DELETE,OPTIONS,PUT");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers","Origin, X-Requested-With, X-Access-Token, X-Api-Key, Content-Type, Accept, Cache-Control");
chain.doFilter(req, res);
}
public void init(FilterConfig arg0) throws ServletException
{
}
}
app.id=YeeAmosFireAutoIntf
\ No newline at end of file
eureka.client.serviceUrl.defaultZone = http://172.16.10.99:10001/eureka/
eureka.client.register-with-eureka = false
eureka.client.fetch-registry = false
eureka.client.healthcheck.enabled = false
eureka.instance.hostname = ${spring.cloud.client.ipAddress}
eureka.instance.statusPageUrlPath = ${management.context-path}/info
eureka.instance.healthCheckUrlPath = ${management.context-path}/health
eureka.instance.preferIpAddress = false
eureka.instance.instance-id = ${spring.cloud.client.ipAddress}:${server.port}
eureka.instance.lease-expiration-duration-in-seconds = 10
eureka.instance.lease-renewal-interval-in-seconds = 5
#\u8BF7\u6C42\u5904\u7406\u7684\u8D85\u65F6\u65F6\u95F4
ribbon.ReadTimeout = 120000
#\u8BF7\u6C42\u8FDE\u63A5\u7684\u8D85\u65F6\u65F6\u95F4
ribbon.ConnectTimeout = 30000
#DB properties:
#spring.datasource.url = jdbc:mysql://172.233.0.6:3306/amos_beijing_command_dev?useSSL=false&allowMultiQueries=true&serverTimezone=Asia/Shanghai
spring.datasource.url = jdbc:mysql://172.16.11.33:3306/amos_iec_test?useSSL=false&allowMultiQueries=true&serverTimezone=Asia/Shanghai
spring.datasource.username = root
spring.datasource.password = admin_1234
spring.datasource.driver-class-name = com.mysql.jdbc.Driver
spring.datasource.type=com.zaxxer.hikari.HikariDataSource
spring.jpa.hibernate.ddl-auto=none
spring.datasource.hikari.minimum-idle=5
spring.datasource.hikari.maximum-pool-size=15
spring.datasource.hikari.auto-commit=true
spring.datasource.hikari.idle-timeout=30000
spring.datasource.hikari.pool-name=DatebookHikariCP
spring.datasource.hikari.max-lifetime=1800000
spring.datasource.hikari.connection-timeout=30000
spring.datasource.hikari.connection-test-query=SELECT 1
#JPA Configuration:
# Show or not log for each sql query
spring.jpa.show-sql = true
# Hibernate ddl auto (create, create-drop, update): with "update" the database
# schema will be automatically updated accordingly to java entities found in
# the project
# Naming strategy
#spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
spring.jpa.hibernate.naming-strategy = org.hibernate.cfg.ImprovedNamingStrategy
# Allows Hibernate to generate SQL optimized for a particular DBMS
spring.jpa.database-platform = org.hibernate.dialect.MySQLDialect
#mybatis mapper file
mybatis.mapper-locations = classpath:db/mapper/*.xml
# mybatis entity package
mybatis.type-aliases-package = com.yeejoin.amos.fireAutoIntf.business.entity.mybatis
#equipment check
param.protocol.not.check = HTTP
#enable Gzip compression
server.compression.enabled = true
server.compression.mime-types = application/json,application/xml,text/html,text/xml,text/plain\u3001
server.compression.min-response-size = 2048
#liquibase
liquibase.change-log = classpath:/db/changelog/changelog-master.xml
liquibase.enabled: true
#redis database index
spring.redis.database=5
#redis ip
spring.redis.host=172.16.11.33
spring.redis.port=6379
#redis password (default is empty)
spring.redis.password=1234560
#max connect number
spring.redis.pool.max-active=200
# redis max wait time ( -1 is not limit)
spring.redis.pool.max-wait=-1
spring.redis.pool.max-idle=10
spring.redis.pool.min-idle=0
spring.redis.timeout=1000
#iec104.debug = false
#iec104.tcp.service.reomteIp=172.233.0.4
#iec104.tcp.service.reomtePort=2404
#iec104.server.Id=1
#iec104.tcp.bind.port=2404
#iec104.client.commonAddress=0000
#iec104.server.start.infomation.address = 1
#iec104.server.consecutive.transmissions.number = 6
#iec104.server.zz.max.transmissions.number = 100
#iec104.server.soe.max.transmissions.number = 10
#iec104.server.sec.max.transmissions.number = 10
\ No newline at end of file
eureka.client.serviceUrl.defaultZone = http://172.233.0.7:10500/eureka/
eureka.client.register-with-eureka = false
eureka.client.fetch-registry = false
eureka.client.healthcheck.enabled = false
eureka.instance.hostname = ${spring.cloud.client.ipAddress}
eureka.instance.statusPageUrlPath = ${management.context-path}/info
eureka.instance.healthCheckUrlPath = ${management.context-path}/health
eureka.instance.preferIpAddress = false
eureka.instance.instance-id = ${spring.cloud.client.ipAddress}:${server.port}
eureka.instance.lease-expiration-duration-in-seconds = 10
eureka.instance.lease-renewal-interval-in-seconds = 5
#\u8BF7\u6C42\u5904\u7406\u7684\u8D85\u65F6\u65F6\u95F4
ribbon.ReadTimeout = 120000
#\u8BF7\u6C42\u8FDE\u63A5\u7684\u8D85\u65F6\u65F6\u95F4
ribbon.ConnectTimeout = 30000
#DB properties:
#spring.datasource.url = jdbc:mysql://172.233.0.6:3306/amos_beijing_command_dev?useSSL=false&allowMultiQueries=true&serverTimezone=Asia/Shanghai
spring.datasource.url = jdbc:mysql://localhost:3306/nr_db?useSSL=false&allowMultiQueries=true&serverTimezone=Asia/Shanghai
spring.datasource.username = root
spring.datasource.password = root_123
spring.datasource.driver-class-name = com.mysql.jdbc.Driver
spring.datasource.type=com.zaxxer.hikari.HikariDataSource
spring.jpa.hibernate.ddl-auto=update
spring.datasource.hikari.minimum-idle=5
spring.datasource.hikari.maximum-pool-size=15
spring.datasource.hikari.auto-commit=true
spring.datasource.hikari.idle-timeout=30000
spring.datasource.hikari.pool-name=DatebookHikariCP
spring.datasource.hikari.max-lifetime=1800000
spring.datasource.hikari.connection-timeout=30000
spring.datasource.hikari.connection-test-query=SELECT 1
#JPA Configuration:
# Show or not log for each sql query
spring.jpa.show-sql = true
# Hibernate ddl auto (create, create-drop, update): with "update" the database
# schema will be automatically updated accordingly to java entities found in
# the project
# Naming strategy
#spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
spring.jpa.hibernate.naming-strategy = org.hibernate.cfg.ImprovedNamingStrategy
# Allows Hibernate to generate SQL optimized for a particular DBMS
spring.jpa.database-platform = org.hibernate.dialect.MySQLDialect
#mybatis mapper file
mybatis.mapper-locations = classpath:db/mapper/*.xml
# mybatis entity package
mybatis.type-aliases-package = com.yeejoin.amos.fireAutoIntf.business.entity.mybatis
#equipment check
param.protocol.not.check = HTTP
#enable Gzip compression
server.compression.enabled = true
server.compression.mime-types = application/json,application/xml,text/html,text/xml,text/plain\u3001
server.compression.min-response-size = 2048
#liquibase
liquibase.change-log = classpath:/db/changelog/changelog-master.xml
liquibase.enabled: false
# Redis\u6570\u636E\u5E93\u7D22\u5F15\uFF08\u9ED8\u8BA4\u4E3A0\uFF09
spring.redis.database=0
# Redis\u670D\u52A1\u5668\u5730\u5740
spring.redis.host=172.16.11.33
# Redis\u670D\u52A1\u5668\u8FDE\u63A5\u7AEF\u53E3
spring.redis.port=6379
# Redis\u670D\u52A1\u5668\u8FDE\u63A5\u5BC6\u7801\uFF08\u9ED8\u8BA4\u4E3A\u7A7A\uFF09
spring.redis.password=
# \u8FDE\u63A5\u6C60\u6700\u5927\u8FDE\u63A5\u6570\uFF08\u4F7F\u7528\u8D1F\u503C\u8868\u793A\u6CA1\u6709\u9650\u5236\uFF09
spring.redis.pool.max-active=200
# \u8FDE\u63A5\u6C60\u6700\u5927\u963B\u585E\u7B49\u5F85\u65F6\u95F4\uFF08\u4F7F\u7528\u8D1F\u503C\u8868\u793A\u6CA1\u6709\u9650\u5236\uFF09
spring.redis.pool.max-wait=-1
# \u8FDE\u63A5\u6C60\u4E2D\u7684\u6700\u5927\u7A7A\u95F2\u8FDE\u63A5
spring.redis.pool.max-idle=10
# \u8FDE\u63A5\u6C60\u4E2D\u7684\u6700\u5C0F\u7A7A\u95F2\u8FDE\u63A5
spring.redis.pool.min-idle=0
# \u8FDE\u63A5\u8D85\u65F6\u65F6\u95F4\uFF08\u6BEB\u79D2\uFF09
spring.redis.timeout=1000
\ No newline at end of file
eureka.client.serviceUrl.defaultZone = http://172.233.0.7:10500/eureka/
eureka.client.register-with-eureka = false
eureka.client.fetch-registry = false
eureka.client.healthcheck.enabled = false
eureka.instance.hostname = ${spring.cloud.client.ipAddress}
eureka.instance.statusPageUrlPath = ${management.context-path}/info
eureka.instance.healthCheckUrlPath = ${management.context-path}/health
eureka.instance.preferIpAddress = false
eureka.instance.instance-id = ${spring.cloud.client.ipAddress}:${server.port}
eureka.instance.lease-expiration-duration-in-seconds = 10
eureka.instance.lease-renewal-interval-in-seconds = 5
#\u8BF7\u6C42\u5904\u7406\u7684\u8D85\u65F6\u65F6\u95F4
ribbon.ReadTimeout = 120000
#\u8BF7\u6C42\u8FDE\u63A5\u7684\u8D85\u65F6\u65F6\u95F4
ribbon.ConnectTimeout = 30000
#DB properties:
#spring.datasource.url = jdbc:mysql://172.233.0.6:3306/amos_beijing_command_dev?useSSL=false&allowMultiQueries=true&serverTimezone=Asia/Shanghai
spring.datasource.url = jdbc:mysql://localhost:3306/nr_db?useSSL=false&allowMultiQueries=true&serverTimezone=Asia/Shanghai
spring.datasource.username = root
spring.datasource.password = root_123
spring.datasource.driver-class-name = com.mysql.jdbc.Driver
#spring.datasource.username = his
#spring.datasource.username = root
#spring.datasource.username = root
#spring.datasource.password = admin_1234
#spring.datasource.password = His@9700
# HikariCP settings
# spring.datasource.hikari.*
# contection life time (ms)
spring.datasource.type=com.zaxxer.hikari.HikariDataSource
spring.jpa.hibernate.ddl-auto=update
spring.datasource.hikari.minimum-idle=5
spring.datasource.hikari.maximum-pool-size=15
spring.datasource.hikari.auto-commit=true
spring.datasource.hikari.idle-timeout=30000
spring.datasource.hikari.pool-name=DatebookHikariCP
spring.datasource.hikari.max-lifetime=1800000
spring.datasource.hikari.connection-timeout=30000
spring.datasource.hikari.connection-test-query=SELECT 1
#JPA Configuration:
# Show or not log for each sql query
spring.jpa.show-sql = true
# Hibernate ddl auto (create, create-drop, update): with "update" the database
# schema will be automatically updated accordingly to java entities found in
# the project
# Naming strategy
#spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
spring.jpa.hibernate.naming-strategy = org.hibernate.cfg.ImprovedNamingStrategy
# Allows Hibernate to generate SQL optimized for a particular DBMS
spring.jpa.database-platform = org.hibernate.dialect.MySQLDialect
#mybatis mapper file
mybatis.mapper-locations = classpath:db/mapper/*.xml
# mybatis entity package
mybatis.type-aliases-package = com.yeejoin.amos.fireAutoIntf.business.entity.mybatis
#equipment check
param.protocol.not.check = HTTP
#enable Gzip compression
server.compression.enabled = true
server.compression.mime-types = application/json,application/xml,text/html,text/xml,text/plain\u3001
server.compression.min-response-size = 2048
#liquibase
liquibase.change-log = classpath:/db/changelog/changelog-master.xml
liquibase.enabled: false
# Redis\u6570\u636E\u5E93\u7D22\u5F15\uFF08\u9ED8\u8BA4\u4E3A0\uFF09
spring.redis.database=0
# Redis\u670D\u52A1\u5668\u5730\u5740
spring.redis.host=172.16.11.33
# Redis\u670D\u52A1\u5668\u8FDE\u63A5\u7AEF\u53E3
spring.redis.port=6379
# Redis\u670D\u52A1\u5668\u8FDE\u63A5\u5BC6\u7801\uFF08\u9ED8\u8BA4\u4E3A\u7A7A\uFF09
spring.redis.password=
# \u8FDE\u63A5\u6C60\u6700\u5927\u8FDE\u63A5\u6570\uFF08\u4F7F\u7528\u8D1F\u503C\u8868\u793A\u6CA1\u6709\u9650\u5236\uFF09
spring.redis.pool.max-active=200
# \u8FDE\u63A5\u6C60\u6700\u5927\u963B\u585E\u7B49\u5F85\u65F6\u95F4\uFF08\u4F7F\u7528\u8D1F\u503C\u8868\u793A\u6CA1\u6709\u9650\u5236\uFF09
spring.redis.pool.max-wait=-1
# \u8FDE\u63A5\u6C60\u4E2D\u7684\u6700\u5927\u7A7A\u95F2\u8FDE\u63A5
spring.redis.pool.max-idle=10
# \u8FDE\u63A5\u6C60\u4E2D\u7684\u6700\u5C0F\u7A7A\u95F2\u8FDE\u63A5
spring.redis.pool.min-idle=0
# \u8FDE\u63A5\u8D85\u65F6\u65F6\u95F4\uFF08\u6BEB\u79D2\uFF09
spring.redis.timeout=1000
spring.application.name = YeeAmosIec104Intf
server.port = 9007
#environment
spring.profiles.active=dev
#netty
so.keepalive = true
so.backlog = 128
#redis
params.remoteurl = http://172.16.11.33:8800/
#params.remoteurl = http://172.16.10.74:8800/
params.time = 5
params.period = 1800
\ No newline at end of file
#周期、循环 - 上行
#PERIODIC = 1,
1=周期、循环
#<para>背景扫描 - 上行</para>
#BACKGROUND_SCAN = 2,
2=背景扫描
#突发(自发) - 上行
#SPONTANEOUS = 3,
3=突发(自发)
#初始化 - 上行
#INITIALIZED = 4,
4=初始化
#请求或者被请求 - 上行、下行
#REQUEST = 5,
5=请求或者被请求
#激活 - 下行
#ACTIVATION = 6,
6=激活
#激活确认 - 上行
#ACTIVATION_CON = 7,
7=激活确认
#停止激活 - 下行
#DEACTIVATION = 8,
8=停止激活
# 停止激活确认 - 上行
#DEACTIVATION_CON = 9,
9=停止激活确认
#激活终止 - 下行
#ACTIVATION_TERMINATION = 10,
10=激活结束
#远方命令引起的返送信息 - 上行
#RETURN_INFO_REMOTE = 11,
11=远方命令引起的返送信息
#当地命令引起的返送信息 - 上行
#RETURN_INFO_LOCAL = 12,
12=当地命令引起的返送信息
# 文件传输
#FILE_TRANSFER = 13,
13=文件传输
#AUTHENTICATION = 14,
14=AUTHENTICATION
#MAINTENANCE_OF_AUTH_SESSION_KEY = 15,
15=MAINTENANCE_OF_AUTH_SESSION_KEY
#MAINTENANCE_OF_USER_ROLE_AND_UPDATE_KEY = 16,
16=MAINTENANCE_OF_USER_ROLE_AND_UPDATE_KEY
#响应站召唤 - 上行
#INTERROGATED_BY_STATION = 20,
20=响应站召唤
#响应第 1 组召唤 - 上行
#INTERROGATED_BY_GROUP_1 = 21,
21=响应第 1 组召唤
#响应第 2 组召唤 - 上行
#INTERROGATED_BY_GROUP_2 = 22,
22=响应第 2 组召唤
#响应第 3 组召唤 - 上行
#INTERROGATED_BY_GROUP_3 = 23,
23=响应第 3 组召唤
#响应第 4 组召唤 - 上行
#INTERROGATED_BY_GROUP_4 = 24,
24=响应第 4 组召唤
#响应第 5 组召唤 - 上行
#INTERROGATED_BY_GROUP_5 = 25,
25=响应第 5 组召唤
#响应第 6 组召唤 - 上行
#INTERROGATED_BY_GROUP_6 = 26,
26=响应第 6 组召唤
#响应第 7 组召唤 - 上行
#INTERROGATED_BY_GROUP_7 = 27,
27=响应第 7 组召唤
#响应第 8 组召唤 - 上行
#INTERROGATED_BY_GROUP_8 = 28,
28=响应第 8 组召唤
#响应第 9 组召唤 - 上行
#INTERROGATED_BY_GROUP_9 = 29,
29=响应第 9 组召唤
#响应第 10 组召唤 - 上行
#INTERROGATED_BY_GROUP_10 = 30,
30=响应第 10 组召唤 - 上行
#响应第 11 组召唤 - 上行
#INTERROGATED_BY_GROUP_11 = 31,
31=响应第 11 组召唤 - 上行
#/// 响应第 12 组召唤 - 上行
#INTERROGATED_BY_GROUP_12 = 32,
32=响应第 12 组召唤 - 上行
info=1
expireDate=2018-4-1,
mac=,
ip=,
licenseType=2
<licenseKey>[-57,-28,-8,41,-121,-46,29,-41,-112,-13,63,-66,-26,-101,24,-69]
#周期、循环 - 上行
#PERIODIC = 1,
1=周期、循环
#<para>背景扫描 - 上行</para>
#BACKGROUND_SCAN = 2,
2=背景扫描
#突发(自发) - 上行
#SPONTANEOUS = 3,
3=突发(自发)
#初始化 - 上行
#INITIALIZED = 4,
4=初始化
#请求或者被请求 - 上行、下行
#REQUEST = 5,
5=请求或者被请求
#激活 - 下行
#ACTIVATION = 6,
6=激活
#激活确认 - 上行
#ACTIVATION_CON = 7,
7=激活确认
#停止激活 - 下行
#DEACTIVATION = 8,
8=停止激活
# 停止激活确认 - 上行
#DEACTIVATION_CON = 9,
9=停止激活确认
#激活终止 - 下行
#ACTIVATION_TERMINATION = 10,
10=激活结束
#远方命令引起的返送信息 - 上行
#RETURN_INFO_REMOTE = 11,
11=远方命令引起的返送信息
#当地命令引起的返送信息 - 上行
#RETURN_INFO_LOCAL = 12,
12=当地命令引起的返送信息
# 文件传输
#FILE_TRANSFER = 13,
13=文件传输
#AUTHENTICATION = 14,
14=AUTHENTICATION
#MAINTENANCE_OF_AUTH_SESSION_KEY = 15,
15=MAINTENANCE_OF_AUTH_SESSION_KEY
#MAINTENANCE_OF_USER_ROLE_AND_UPDATE_KEY = 16,
16=MAINTENANCE_OF_USER_ROLE_AND_UPDATE_KEY
#响应站召唤 - 上行
#INTERROGATED_BY_STATION = 20,
20=响应站召唤
#响应第 1 组召唤 - 上行
#INTERROGATED_BY_GROUP_1 = 21,
21=响应第 1 组召唤
#响应第 2 组召唤 - 上行
#INTERROGATED_BY_GROUP_2 = 22,
22=响应第 2 组召唤
#响应第 3 组召唤 - 上行
#INTERROGATED_BY_GROUP_3 = 23,
23=响应第 3 组召唤
#响应第 4 组召唤 - 上行
#INTERROGATED_BY_GROUP_4 = 24,
24=响应第 4 组召唤
#响应第 5 组召唤 - 上行
#INTERROGATED_BY_GROUP_5 = 25,
25=响应第 5 组召唤
#响应第 6 组召唤 - 上行
#INTERROGATED_BY_GROUP_6 = 26,
26=响应第 6 组召唤
#响应第 7 组召唤 - 上行
#INTERROGATED_BY_GROUP_7 = 27,
27=响应第 7 组召唤
#响应第 8 组召唤 - 上行
#INTERROGATED_BY_GROUP_8 = 28,
28=响应第 8 组召唤
#响应第 9 组召唤 - 上行
#INTERROGATED_BY_GROUP_9 = 29,
29=响应第 9 组召唤
#响应第 10 组召唤 - 上行
#INTERROGATED_BY_GROUP_10 = 30,
30=响应第 10 组召唤 - 上行
#响应第 11 组召唤 - 上行
#INTERROGATED_BY_GROUP_11 = 31,
31=响应第 11 组召唤 - 上行
#/// 响应第 12 组召唤 - 上行
#INTERROGATED_BY_GROUP_12 = 32,
32=响应第 12 组召唤 - 上行
soe.time=60
status.time=20
\ No newline at end of file
1=单点信息
3=双点信息
5=步位置信息
7=32比特串
9=测量值,归一化值
11=测量值,标度化值
13=测量值,短浮点数
15=累计量
20=带状态检出的成组单点信息
21=不带品质描述的归一化测量值
30=带时标CP56Time2a的单点信息
31=带时标CP56Time2a的双点信息
32=带时标CP56Time2a的步位置信息
33=带时标CP56Time2a的32比特串
34=带时标CP56Time2a的测量值,归一化值
35=带时标CP56Time2a的测量值,标度化值
36=带时标CP56Time2a的测量值,短浮点数
37=带时标CP56Time2a的累计量
38=带时标CP56Time2a的继电保护装置事件
39=带时标CP56Time2a的继电保护装置成组启动事件
40=带时标CP56Time2a的继电保护装置成组输出电路信息
45=单命令
46=双命令
47=步调节命令
48=设点命令,归一化值
49=设点命令,标度化值
50=设点命令,短浮点数
51=32比特串
58=带时标CP56Time2a的单命令
59=带时标CP56Time2a的双命令
60=带时标CP56Time2a的步调节命令
61=带时标CP56Time2a的设点命令,归一化值
62=带时标CP56Time2a的设点命令,标度化值
63=带时标CP56Time2a的设点命令,短浮点数
64=带时标CP56Time2a的32比特串
100=总召唤命令
101=计数量召唤命令
102=读命令
103=时钟同步命令
105=复位进程命令
107=带时标CP56Time2a的测试命令
<?xml version="1.0" encoding="utf-8"?>
<databaseChangeLog
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.4.xsd">
<include file="i_client_linsten.sql" relativeToChangelogFile="true"/>
<include file="i_transmit_mapper.sql" relativeToChangelogFile="true"/>
</databaseChangeLog>
\ No newline at end of file
/*
Navicat MySQL Data Transfer
Source Server : 172.16.11.33
Source Server Version : 50717
Source Host : 172.16.11.33:3306
Source Database : amos_iec
Target Server Type : MYSQL
Target Server Version : 50717
File Encoding : 65001
Date: 2019-11-07 15:05:38
*/
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for i_client_linsten
-- ----------------------------
DROP TABLE IF EXISTS `i_client_linsten`;
CREATE TABLE `i_client_linsten` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`channle_no` varchar(255) DEFAULT NULL,
`data_type` varchar(255) DEFAULT NULL,
`remark` varchar(255) DEFAULT NULL,
`url` varchar(255) DEFAULT NULL,
`name` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4;
-- ----------------------------
-- Table structure for i_ip_port_conf
-- ----------------------------
DROP TABLE IF EXISTS `i_ip_port_conf`;
CREATE TABLE `i_ip_port_conf` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`channel_no` varchar(255) DEFAULT NULL,
`common_address` varchar(255) DEFAULT NULL,
`ip` varchar(255) DEFAULT NULL,
`is_delete` int(11) NOT NULL,
`last_update_time` datetime DEFAULT NULL,
`port` varchar(255) DEFAULT NULL,
`service_id` varchar(255) DEFAULT NULL,
`service_type` varchar(255) DEFAULT NULL,
`name` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8mb4;
-- ----------------------------
-- Table structure for i_point_config
-- ----------------------------
DROP TABLE IF EXISTS `i_point_config`;
CREATE TABLE `i_point_config` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`channel_no` varchar(255) DEFAULT NULL,
`common_address` bigint(20) DEFAULT NULL,
`invalid` bit(1) NOT NULL,
`name` varchar(255) DEFAULT NULL,
`originator_address` int(11) DEFAULT NULL,
`point_code` varchar(255) DEFAULT NULL,
`remark` varchar(255) DEFAULT NULL,
`value` varchar(255) DEFAULT NULL,
`point_type` varchar(255) DEFAULT NULL,
`point_classify` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2988 DEFAULT CHARSET=utf8mb4;
SET FOREIGN_KEY_CHECKS=1;
/*
Navicat Premium Data Transfer
Source Server : 172.16.11.33
Source Server Type : MySQL
Source Server Version : 50717
Source Host : 172.16.11.33:3306
Source Schema : amos_iec_test
Target Server Type : MySQL
Target Server Version : 50717
File Encoding : 65001
Date: 25/11/2019 19:50:58
*/
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for i_transmit_mapper
-- ----------------------------
DROP TABLE IF EXISTS `i_transmit_mapper`;
CREATE TABLE `i_transmit_mapper` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`mapper_id` bigint(20) NULL DEFAULT NULL,
`mapper_type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
`transmit_ip` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
`transmit_port` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
`transmit_type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
`transmit_url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of i_transmit_mapper
-- ----------------------------
INSERT INTO `i_transmit_mapper` VALUES (1, 2, 'UART', '172.16.3.3', NULL, 'TCP', '172.16.3.3');
-- ----------------------------
-- Table structure for i_uart_config
-- ----------------------------
DROP TABLE IF EXISTS `i_uart_config`;
CREATE TABLE `i_uart_config` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`baud_rate` int(11) NOT NULL,
`create_by` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
`created_time` datetime(0) NULL DEFAULT NULL,
`data_bits` int(11) NOT NULL,
`is_delete` int(11) NOT NULL,
`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
`parity` int(11) NOT NULL,
`remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
`serial_port` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
`stop_bits` int(11) NOT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of i_uart_config
-- ----------------------------
INSERT INTO `i_uart_config` VALUES (2, 9600, NULL, NULL, 8, 0, 'COM4', 1, NULL, 'COM4', 1);
INSERT INTO `i_uart_config` VALUES (3, 9600, NULL, NULL, 8, 0, 'COM3', 1, NULL, 'COM3', 1);
SET FOREIGN_KEY_CHECKS = 1;
Wed Mar 1 12:05:10 MST 2006
We forgot to update the Mac OS X binary. Previously, it was an old version
(RXTX-2.1-7pre20). This has now been corrected.
log4j.rootLogger=DEBUG, stdout, logfile
log4j.logger.io.netty=info
log4j.logger.org.hibernate=info
log4j.logger.com.mchange=info
log4j.logger.org.springframework=info
log4j.logger.com.mangofactory=info
log4j.logger.org.apache=info
log4j.logger.com.zaxxer.hikari.pool=info
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %t %-5p [%c{1}:%L] %m%n
log4j.appender.logfile=org.apache.log4j.RollingFileAppender
log4j.appender.logfile.File=logs/fireAutoIntf.log
log4j.appender.logfile.MaxFileSize=10240KB
log4j.appender.logfile.MaxBackupIndex=30
log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
log4j.appender.logfile.layout.ConversionPattern=%d %t %-5p [%c{1}:%L] %m%n
<?xml version="1.0" encoding="UTF-8"?>
<assembly
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3 http://maven.apache.org/xsd/assembly-1.1.3.xsd">
<id>package</id>
<formats>
<format>zip</format>
</formats>
<includeBaseDirectory>true</includeBaseDirectory>
<fileSets>
<fileSet>
<directory>bin</directory>
<outputDirectory>/</outputDirectory>
</fileSet>
<fileSet>
<directory>src/main/resources/config</directory>
<outputDirectory>/config/</outputDirectory>
</fileSet>
<fileSet>
<directory>src/main/resources/db</directory>
<outputDirectory>/db</outputDirectory>
</fileSet>
<fileSet>
<directory>src/main/resources/lib</directory>
<outputDirectory>/lib</outputDirectory>
</fileSet>
<fileSet>
<directory>src/main/resources</directory>
<includes>
<include>application.properties</include>
<include>application-dev.properties</include>
<include>application-prod.properties</include>
<include>application-test.properties</include>
<include>cause.properties</include>
<include>debug.properties</include>
<include>typeId.properties</include>
<include>point.json</include>
<include>soe.json</include>
<include>log4j.properties</include>
<include>META-INF/app.properties</include>
</includes>
<outputDirectory>/</outputDirectory>
</fileSet>
<fileSet>
<directory>${project.build.directory}</directory>
<outputDirectory>/</outputDirectory>
<includes>
<include>*.jar</include>
</includes>
</fileSet>
</fileSets>
<dependencySets>
<dependencySet>
<outputDirectory>lib</outputDirectory>
<scope>runtime</scope>
<!-- <unpack>false</unpack> -->
<excludes>
<!-- <exclude>${project.name}-${project.version}</exclude> -->
<exclude>${groupId}:${artifactId}</exclude>
</excludes>
</dependencySet>
</dependencySets>
</assembly>
\ No newline at end of file
1=单点信息
3=双点信息
5=步位置信息
7=32比特串
9=测量值,归一化值
11=测量值,标度化值
13=测量值,短浮点数
15=累计量
20=带状态检出的成组单点信息
21=不带品质描述的归一化测量值
30=带时标CP56Time2a的单点信息
31=带时标CP56Time2a的双点信息
32=带时标CP56Time2a的步位置信息
33=带时标CP56Time2a的32比特串
34=带时标CP56Time2a的测量值,归一化值
35=带时标CP56Time2a的测量值,标度化值
36=带时标CP56Time2a的测量值,短浮点数
37=带时标CP56Time2a的累计量
38=带时标CP56Time2a的继电保护装置事件
39=带时标CP56Time2a的继电保护装置成组启动事件
40=带时标CP56Time2a的继电保护装置成组输出电路信息
45=单命令
46=双命令
47=步调节命令
48=设点命令,归一化值
49=设点命令,标度化值
50=设点命令,短浮点数
51=32比特串
58=带时标CP56Time2a的单命令
59=带时标CP56Time2a的双命令
60=带时标CP56Time2a的步调节命令
61=带时标CP56Time2a的设点命令,归一化值
62=带时标CP56Time2a的设点命令,标度化值
63=带时标CP56Time2a的设点命令,短浮点数
64=带时标CP56Time2a的32比特串
100=总召唤命令
101=计数量召唤命令
102=读命令
103=时钟同步命令
105=复位进程命令
107=带时标CP56Time2a的测试命令
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>YeeAmosIec104IntfServer</artifactId>
<name>YeeAmosIec104IntfServer</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<drools.version>6.5.0.Final</drools.version>
</properties>
<parent>
<groupId>com.yeejoin.amos</groupId>
<artifactId>YeeAmosIec104IntfRoot</artifactId>
<version>1.0.0</version>
</parent>
<dependencies>
<!-- 安全模块jar -->
<dependency>
<groupId>com.yeejoin.amos</groupId>
<artifactId>AmosOPService</artifactId>
<version>${YeeOp.version}</version>
</dependency>
<dependency>
<groupId>com.yeejoin.amos</groupId>
<artifactId>YeeAmosConnentCommon</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>com.yeejoin.amos</groupId>
<artifactId>amos-authtoken</artifactId>
<version>${YeeSecurity.version}</version>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.yeejoin.amos</groupId>
<artifactId>YeeAmosConnentCommon</artifactId>
<version>1.0.0</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>
\ No newline at end of file
/**
*
*/
package com.yeejoin.amos.iec104.business.constants;
import org.apache.log4j.Logger;
import java.text.SimpleDateFormat;
/**
* iot常量
*
* @author as-youjun
*/
public class IEC104Constant {
/**
* 构造方法
*/
private IEC104Constant() {
Logger.getLogger(this.getClass()).debug(IEC104Constant.CONSTRUCTOR);
}
/**
* 网络服务ip
*/
public static final String NET_SERVER_HOST = "0.0.0.0";
/**
* 时间格式(yyyy-MM-dd HH:mm:ss)
*/
public static final SimpleDateFormat SIMPLEDATAFORMAT_YMDHMS = new SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss");
/**
* 构造方法字符串
*/
public static final String CONSTRUCTOR = "constructor...";
/**
* 轮询job最大线程数
*/
public static final int POLLING_JOB_THREAD_MAX_NUM = 20;
/**
* amos线程池数量
*/
public static final int AMOS_THREAD_NUM = 20;
/**
* 设备测试最大线程数
*/
public static final int TEST_EQUIPMENT_THREAD_MAX_NUM = 5;
/**
* 时间格式字符串:yyyy-MM-dd HH:mm:ss
*/
public static final String DATE_TIME_STR_YMDHMS = "yyyy-MM-dd HH:mm:ss";
/**
* bar
*/
public static final String BAR = "-";
/**
* Underline
*/
public static final String UNDERLINE = "_";
/**
* user
*/
public static final String USER = "user";
/**
* token
*/
public static final String TOKEN = "token";
/**
* loginType
*/
public static final String LOGIN_TYPE = "loginType";
/**
* subGraphId
*/
public static final String SUB_GRAPH_ID = "subGraphId";
public static final String ADMIN_ID = "1";
/**
* 帧报文异常
*/
public static final String FRAME_EXECPTION = "FRAME";
/**
* 性能指标
*/
public static final String METRIC = "METRIC";
/**
* 报文通道
*/
public static final String CHANNEL = "CHANNEL";
/**
* 设备状态(掉线)告警
*/
public static final String EQUIPMENT_STATUS = "EQUIPMENT_STATUS";
/**
* 设备连通性告警告警
*/
public static final String EQUIPMENT_CONNECTION = "EQUIPMENT_CONNECTION";
/**
* 通道注册
*/
public static final String REGISTER = "REGISTER";
/**
* 通道注销
*/
public static final String UNREGISTER = "UNREGISTER";
/**
* 报文正常
*/
public static final String NORMAL = "NORMAL";
/**
* 报文异常
*/
public static final String UNNORMAL = "UNNORMAL";
/**
* 告警socket类型
*/
public static final String ALARM_SOCKET = "ALARM_SOCKET";
/**
* 数据socket类型
*/
public static final String METRIC_SOCKET = "METRIC_SOCKET";
/**
* 数据socket类型
*/
public static final String MORPHIC_SOCKET = "MORPHIC_SOCKET";
/**
* false
*/
public static final Boolean FAIL_BOOLEAN_VALUE = Boolean.FALSE;
/**
* 0
*/
public static final Integer ZERO_INT_VALUE = Integer.parseInt("0");
/**
* -1
*/
public static final Integer FAIL_INT_VALUE = Integer.parseInt("-1");
/**
* -1
*/
public static final Long FAIL_LONG_VALUE = Long.parseLong("-1");
/**
* -1
*/
public static final Short FAIL_SHORT_VALUE = Short.parseShort("-1");
/**
*
*/
public static final Float FAIL_FLOAT_VALUE = Float.parseFloat("-1");
/**
* -1
*/
public static final Double FAIL_DOUBLE_VALUE = Double.parseDouble("-1");
/**
* 空格
*/
public static final Character FAIL_CHARACTER_VALUE = Character.valueOf(' ');
/**
* 失败
*/
public static final int FAILURE = 0;
/**
* 成功
*/
public static final int SUCCESS = 1;
/**
* 在线
*/
public static final String ONLINE = "在线";
/**
* 掉线
*/
public static final String OFFLINE = "掉线";
/**
* 通
*/
public static final String OPEN = "通";
/**
* 不通
*/
public static final String OFF = "不通";
/**
* ip
*/
public static final String IP = "ip";
/**
* #
*/
public static final String SHARP = "#";
/**
* 设备相关常量
*
* @author as-youjun
*/
public static final class EquipmentConstant {
/**
* 下划线
*/
public static final String UNDERLINE = "_";
/**
* 设备属性key前缀
*/
public static final String KEY_PREFIX_EQUIP = "equip_";
/**
* 能力属性key前缀
*/
public static final String KEY_PREFIX_CPBL = "cpbl_";
/**
* 接口属性key前缀
*/
public static final String KEY_PREFIX_INTFC = "intfc_";
/**
* 测试设备标识
*/
public static final String TEST_EQUIPMENT = "test_equipment";
/**
* 选择接口key
*/
public static final String KEY_SELINTFCIDS = "selIntfcIds";
/**
* 选择能力key
*/
public static final String KEY_SELCPBLIDS = "selCpblIds";
/**
* 测试接口标识
*/
public static final String CONNECT = "connect";
/**
* 测试指标标识
*/
public static final String METRIC = "metric";
/**
* 测试接口key
*/
public static final String CONNECTDATA = "connectData";
/**
* 测试指标key
*/
public static final String METRICDATA = "metricData";
/**
* sourceId
*/
public static final String SOURCEID = "sourceId";
/**
* frameType
*/
public static final String FRAMETYPE = "frameType";
/**
* labelType
*/
public static final String LABELTYPE = "labelType";
/**
* quotaSelected
*/
public static final String QUOTASELECTED = "quotaSelected";
/**
* eqpId设备id
*/
public static final String EQPID = "eqpId";
/**
* 设备连通性判断时长:超过eqp_connected_time_span毫秒的缓存数据无效!!!
*/
public static final long EQP_CONNECTED_TIME_SPAN = 120000;//2分钟
}
/**
* TCP
*/
public static final String TCP = "TCP";
public static final String PIE_CHAR = "pieChar";
public static final String BAR_CHAR = "barChar";
public static final String HBAR_CHAR = "hbarChar";
public static final String LINE_CHAR = "lineChar";
public static final String DOUGHUNT_CHAR = "doughuntChar";
public static final String ROSE_CHAR = "roseChar";
public static final String AREA_CHAR = "areaChar";
public static final String DIMENSION = "dimension";
public static final String MEASURE = "measure";
public static final String ALARM_MESSAGE = "alarm";
public static final String GENERAL_MESSAGE = "general";
}
package com.yeejoin.amos.iec104.business.controller;
import java.util.HashMap;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.yeejoin.amos.security.authorization.Authorization;
import com.yeejoin.amos.security.common.remote.RemoteSecurityServer;
import com.yeejoin.amos.security.entity.User;
import springfox.documentation.annotations.ApiIgnore;
/**
* 基础控制器
*
* @author
*
*/
@ApiIgnore
@RestController
@RequestMapping("/base")
@Authorization
public class BaseController {
@Autowired
private RemoteSecurityServer remoteSecurityServer;
@Autowired
protected HttpServletRequest request;
/**
* 成功返回状态
*/
protected static final String SUCCESS = "SUCCESS";
/**
* 失败返回状态
*/
protected static final String FAILED = "FAILED";
/**
* 默认页大小
*/
protected static final int DEFAULT_PAGE_SIZE = 10;
protected String getToken()
{
/* Get token from header */
String authToken = request.getHeader("X-Access-Token");
/* If token not found get it from request parameter */
if (authToken == null)
{
authToken = request.getParameter("token");
}
return authToken;
}
/**
*
* <pre>
* 判断当前用户角色级别:true:主管/false:装备管理员
* </pre>
*
* @return
*/
protected boolean isDirector()
{
if(getUserInfo() == null){
return false;
}
return getUserInfo().getRole().getRoleType() != 3;
}
/**
* 获取用户角色id
* @return
*/
protected String getRoleId()
{
if(getUserInfo() == null){
return "";
}
return getUserInfo().getRole().getRoleType().toString();
}
/**
* 当前登录用户信息
*/
protected User getUserInfo() {
if(getToken() == null){
return null;
}
return remoteSecurityServer.loginAuthentication(getToken());
}
protected Long getUserId()
{
Long userId = null;
if (getUserInfo() != null)
{
userId = getUserInfo().getId();
}
return userId;
}
/**
* 获取当前用户所属公司名称
* @return
*/
protected String getCurrentCompanyNameOfUser(){
if(getUserInfo() == null){
return "";
}
return getUserInfo().getCompany().getCompanyName();
}
/**
* 获取请求的cookies
* @return
*/
protected HashMap<String,String> getCookInfoMap(){
HashMap<String,String> map = new HashMap<String,String>();
Cookie[] cookies = request.getCookies();
if(cookies!=null){
for(Cookie ck:cookies){
map.put(ck.getName(), ck.getValue());
}
}
return map;
}
/**
* 获取公司orgcode
* @return
*/
protected String getOrgCode(){
if(getUserInfo() == null){
return "";
}
return getUserInfo().getCompany().getCompCode();
}
}
package com.yeejoin.amos.iec104.business.controller;
import java.util.Date;
import com.yeejoin.amos.connect.dao.entity.ClientListenVo;
import com.yeejoin.amos.connect.dao.entity.ConfigVo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.yeejoin.amos.iec104.business.param.ClientParam;
import com.yeejoin.amos.iec104.business.service.intfc.IClientListenService;
import com.yeejoin.amos.iec104.business.service.intfc.IConfService;
import com.yeejoin.amos.iec104.tcp.TcpServer;
import com.yeejoin.amos.iec104.tcp.client.IEC104ClientManager;
import com.yeejoin.amos.iec104.utils.NetUtil;
import com.yeejoin.amos.op.core.common.response.CommonResponse;
import com.yeejoin.amos.op.core.util.CommonResponseUtil;
import com.yeejoin.amos.security.authorization.Authorization;
import io.swagger.annotations.Api;
@RestController
@RequestMapping(value = "/iec")
@Api(tags="客户端api")
public class ClientController extends BaseController{
private final Logger log = LoggerFactory.getLogger(ClientController.class);
@Autowired
IEC104ClientManager clientManager;
@Autowired
IConfService confService;
@Autowired
IClientListenService clientListenService;
@Autowired
TcpServer tcpServer;
@PostMapping(value="/create",produces = "application/json;charset=UTF-8")
@Authorization(ingore=true)
public CommonResponse createClient(@RequestBody ClientParam client) {
try {
String no = confService.getMaxNo();
ConfigVo vo = new ConfigVo();
vo.setIp(client.getIp());
vo.setPort(client.getPort());
vo.setCommonAddress(client.getCommonAddress());
vo.setIsDelete(0);
vo.setLastUpdateTime(new Date());
vo.setServiceType(client.getServiceType());
vo.setServiceId(String.format("S%06d", Integer.valueOf(no)+1));
vo.setChannelNo(String.format("N%06d", Integer.valueOf(no)+1));
vo.setName(client.getName());
if ("IEC_CLIENT".equals(vo.getServiceType())) {
if (NetUtil.isLoclePortUsing(Integer.valueOf(client.getPort()))) {
return CommonResponseUtil.failure("端口已经被占用");
}
}
confService.add(vo);
if ("IEC_SERVER".equals(vo.getServiceType())) {
clientManager.createClient(vo.getIp(), vo.getPort(), vo.getCommonAddress());
} else if ("IEC_CLIENT".equals(vo.getServiceType())) {
tcpServer.createIecService(vo.getId(), vo.getPort());
}
return CommonResponseUtil.success();
} catch (Exception e) {
log.error(e.getMessage(), e);
return CommonResponseUtil.failure("创建客户端失败");
}
}
@PostMapping(value="/save",produces = "application/json;charset=UTF-8")
@Authorization(ingore=true)
public CommonResponse save(@RequestBody ConfigVo vo) {
try {
if (ObjectUtils.isEmpty(vo)) {
return CommonResponseUtil.failure("参数错误");
}
if ("IEC_SERVER".equals(vo.getServiceType()) && !ObjectUtils.isEmpty(vo.getId())) {
clientManager.closeClient(vo.getIp(), vo.getPort());
}
ConfigVo oldVo = confService.getServerById(vo.getId());
confService.add(vo);
if ("IEC_SERVER".equals(vo.getServiceType())) {
clientManager.createClient(vo.getIp(), vo.getPort(), vo.getCommonAddress());
}
if ("IEC_CLIENT".equals(vo.getServiceType())) {
if (oldVo.getPort().equals(vo.getPort())) {
tcpServer.closeIecService(vo.getId());
tcpServer.createIecService(vo.getId(), vo.getPort());
} else {
if (NetUtil.isLoclePortUsing(Integer.valueOf(vo.getPort()))) {
return CommonResponseUtil.failure("端口已经被占用");
}
tcpServer.createIecService(vo.getId(), vo.getPort());
}
}
return CommonResponseUtil.success();
} catch (Exception e) {
log.error(e.getMessage(), e);
return CommonResponseUtil.failure("创建客户端失败");
}
}
@GetMapping(value="/getAllClient",produces = "application/json;charset=UTF-8")
@Authorization(ingore=true)
public CommonResponse getAllClients() {
try {
return CommonResponseUtil.success(confService.getServerByType("IEC_CLIENT"));
} catch (Exception e) {
log.error(e.getMessage(), e);
return CommonResponseUtil.failure("创建客户端失败");
}
}
@GetMapping(value="/getAllService",produces = "application/json;charset=UTF-8")
@Authorization(ingore=true)
public CommonResponse getAllService() {
try {
return CommonResponseUtil.success(confService.getServerByType("IEC_SERVER"));
} catch (Exception e) {
log.error(e.getMessage(), e);
return CommonResponseUtil.failure("创建客户端失败");
}
}
@GetMapping(value="/client/{serviceId}",produces = "application/json;charset=UTF-8")
@Authorization(ingore=true)
public CommonResponse getService(@PathVariable("serviceId") String serviceId) {
try {
return CommonResponseUtil.success(confService.getServerByServiceId(serviceId));
} catch (Exception e) {
log.error(e.getMessage(), e);
return CommonResponseUtil.failure("客户端详情获取失败");
}
}
@GetMapping(value="/subscriber/{serviceId}",produces = "application/json;charset=UTF-8")
@Authorization(ingore=true)
public CommonResponse getSubscriber(@PathVariable("serviceId") String serviceId) {
try {
return CommonResponseUtil.success(clientListenService.getDataByServiceId(serviceId));
} catch (Exception e) {
e.printStackTrace();
return CommonResponseUtil.failure(e.getMessage());
}
}
@PostMapping(value="/subscriber/add",produces = "application/json;charset=UTF-8")
@Authorization(ingore=true)
public CommonResponse addSubscriber(@RequestBody ClientListenVo listener) {
try {
clientListenService.add(listener);
return CommonResponseUtil.success();
} catch (Exception e) {
e.printStackTrace();
return CommonResponseUtil.failure(e.getMessage());
}
}
@DeleteMapping(value="/subscriber/delete/{id}",produces = "application/json;charset=UTF-8")
@Authorization(ingore=true)
public CommonResponse deleteSubscriber(@PathVariable("id") Long id) {
try {
clientListenService.del(id);
return CommonResponseUtil.success();
} catch (Exception e) {
e.printStackTrace();
return CommonResponseUtil.failure(e.getMessage());
}
}
@PutMapping(value="/subscriber/update",produces = "application/json;charset=UTF-8")
@Authorization(ingore=true)
public CommonResponse updateSubscriber(@RequestBody ClientListenVo listener) {
try {
clientListenService.add(listener);
return CommonResponseUtil.success();
} catch (Exception e) {
e.printStackTrace();
return CommonResponseUtil.failure(e.getMessage());
}
}
@PostMapping(value="/close",produces = "application/json;charset=UTF-8")
@Authorization(ingore=true)
public CommonResponse closeClient(@RequestBody ConfigVo vo) {
try {
confService.delete(vo.getId());
clientManager.closeClient(vo.getIp(), vo.getPort());
return CommonResponseUtil.success();
} catch (Exception e) {
log.error(e.getMessage(), e);
return CommonResponseUtil.failure("关闭客户端失败");
}
}
@DeleteMapping(value="/delete/{id}",produces = "application/json;charset=UTF-8")
@Authorization(ingore=true)
public CommonResponse deleteClient(@PathVariable("id") Long id) {
try {
ConfigVo vo = confService.findById(id);
if ("IEC_SERVER".equals(vo.getServiceType())) {
clientManager.closeClient(vo.getIp(), vo.getPort());
} else {
tcpServer.closeIecService(vo.getId());
}
confService.delete(id);
return CommonResponseUtil.success();
} catch (Exception e) {
e.printStackTrace();
return CommonResponseUtil.failure(e.getMessage());
}
}
@PostMapping(value="/reset",produces = "application/json;charset=UTF-8")
@Authorization(ingore=true)
public CommonResponse reset() {
try {
return CommonResponseUtil.success();
} catch (Exception e) {
log.error(e.getMessage(), e);
return CommonResponseUtil.failure("关闭客户端失败");
}
}
}
package com.yeejoin.amos.iec104.business.controller;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import com.yeejoin.amos.connect.dao.entity.ConfigVo;
import com.yeejoin.amos.connect.dao.entity.PointConfigVo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import com.yeejoin.amos.iec104.business.param.PointParam;
import com.yeejoin.amos.iec104.business.service.intfc.IConfService;
import com.yeejoin.amos.iec104.business.service.intfc.IPointConfigService;
import com.yeejoin.amos.iec104.tcp.server.session.Session;
import com.yeejoin.amos.iec104.tcp.server.session.SessionManager;
import com.yeejoin.amos.iec104.utils.ExcelUtils;
import com.yeejoin.amos.op.core.common.response.CommonResponse;
import com.yeejoin.amos.op.core.util.CommonResponseUtil;
import com.yeejoin.amos.security.authorization.Authorization;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
@RestController
@RequestMapping(value = "/point")
@Api(tags="转发表配置")
public class PointController extends BaseController{
private final Logger log = LoggerFactory.getLogger(PointController.class);
@Autowired
private IConfService confService;
@Autowired
private IPointConfigService pointConfigService;
/**
* 巡检点状态发生变化
*
* @param ids
* @return
*/
// @ApiOperation(value = "巡检点状态发生变化", notes = "巡检点状态发生变化")
// @PostMapping(value = "/noticePointChange", produces = "application/json;charset=UTF-8")
// @Authorization(ingore=true)
// public CommonResponse noticePointChange(@ApiParam(value = "巡检点ID", required = true)@RequestBody(required = false) List<Long> ids) {
// try {
// log.debug("巡检点ID pointId======="+ids);
// if (ObjectUtils.isEmpty(ids)) {
// return CommonResponseUtil.failure("巡检点ID不可以为空");
// }
// return CommonResponseUtil.success();
// } catch (Exception e) {
// log.error(e.getMessage(), e);
// return CommonResponseUtil.failure("消息通知失败");
// }
// }
@ApiOperation(value = "导出模板", notes = "导出模板")
@RequestMapping(value = "/export/model", method = RequestMethod.GET)
@Authorization(ingore=true)
public CommonResponse exportModel(HttpServletResponse response) {
List<PointConfigVo> list = new ArrayList<>();
list.add(new PointConfigVo());
try {
ExcelUtils.writeExcel(response, null, PointConfigVo.class);
} catch (Exception e) {
e.printStackTrace();
}
return CommonResponseUtil.success();
}
@ApiOperation(value = "导入转发表", notes = "导入转发表")
@RequestMapping(value = "/import", method = RequestMethod.POST)
@Authorization(ingore=true)
public CommonResponse importClientPoint(@RequestParam(value="file", required = false) MultipartFile file, @RequestParam("serviceId") String serviceId,@RequestParam("pointType") String pointType) {
if (ObjectUtils.isEmpty(serviceId)) {
return CommonResponseUtil.success();
}
ConfigVo vo = confService.getServerByServiceId(serviceId);
List<PointConfigVo> list = ExcelUtils.readExcel("", PointConfigVo.class, file);
list.forEach(
b -> {
b.setChannelNo(vo.getChannelNo());
b.setPointType(pointType);
}
);
pointConfigService.save(list);
return CommonResponseUtil.success();
}
@ApiOperation(value = "导入转发表", notes = "导入转发表")
@RequestMapping(value = "/delete/{serviceId}", method = RequestMethod.DELETE)
@Authorization(ingore=true)
public CommonResponse deleteClientPoint(@PathVariable("serviceId") String serviceId) {
if (ObjectUtils.isEmpty(serviceId)) {
return CommonResponseUtil.success();
}
ConfigVo vo = confService.getServerByServiceId(serviceId);
pointConfigService.deleteByChannelNo(vo.getChannelNo());
return CommonResponseUtil.success();
}
// @ApiOperation(value = "导入转发表", notes = "导入转发表")
// @RequestMapping(value = "/service/import", method = RequestMethod.POST)
// @Authorization(ingore=true)
// public CommonResponse importServicePoint(@RequestParam(value="uploadFile", required = false) MultipartFile file, @RequestParam("serviceId") String serviceId,@RequestParam("pointType") String pointType) {
// ConfigVo vo = confService.getServerByTypeAndServiceId("IEC_SERVER", serviceId);
// List<PointConfigVo> list = ExcelUtils.readExcel("", PointConfigVo.class, file);
//
// list.forEach(
// b -> {
// b.setChannelNo(vo.getChannelNo());
// b.setPointType(pointType);
// }
// );
// pointConfigService.save(list);
// return CommonResponseUtil.success();
// }
@ApiOperation(value = "根据通道编码获取摇信点数据", notes = "根据通道编码获取点数据")
@RequestMapping(value = "/yx/{serviceId}", method = RequestMethod.GET)
@Authorization(ingore=true)
public CommonResponse getYxPointByChannelNo(@PathVariable("serviceId") String serviceId) {
if (ObjectUtils.isEmpty(serviceId)) {
return CommonResponseUtil.success();
}
ConfigVo vo = confService.getServerByServiceId(serviceId);
if (ObjectUtils.isEmpty(vo)) {
return CommonResponseUtil.success();
}
return CommonResponseUtil.success(pointConfigService.getAllYXPointData(vo.getChannelNo()));
}
@ApiOperation(value = "根据通道编码获取摇信点数据", notes = "根据通道编码获取点数据")
@RequestMapping(value = "/pointType/{serviceId}", method = RequestMethod.GET)
@Authorization(ingore=true)
public CommonResponse getYxPointType(@PathVariable("serviceId") String serviceId) {
if (ObjectUtils.isEmpty(serviceId)) {
return CommonResponseUtil.success();
}
ConfigVo vo = confService.getServerByServiceId(serviceId);
if (ObjectUtils.isEmpty(vo)) {
return CommonResponseUtil.failure("没有相关服务接口");
}
List<String> list = pointConfigService.getYcPointType(vo.getChannelNo());
return CommonResponseUtil.success(list);
}
@ApiOperation(value = "根据通道编码获取遥测点数据", notes = "根据通道编码获取点数据")
@RequestMapping(value = "/yc/{serviceId}", method = RequestMethod.GET)
@Authorization(ingore=true)
public CommonResponse getYcPointByChannelNo(@PathVariable("serviceId") String serviceId) {
if (ObjectUtils.isEmpty(serviceId)) {
return CommonResponseUtil.success();
}
ConfigVo vo = confService.getServerByServiceId(serviceId);
if (ObjectUtils.isEmpty(vo)) {
return CommonResponseUtil.success();
}
return CommonResponseUtil.success(pointConfigService.getAllYCPointData(vo.getChannelNo()));
}
@ApiOperation(value = "触发告警", notes = "触发告警")
@RequestMapping(value = "/trigger/soe", method = RequestMethod.PUT)
@Authorization(ingore=true)
public CommonResponse triggerSOE(@RequestBody PointParam point) {
log.info(point.toString());
PointConfigVo vo = pointConfigService.findPointByPointCode(point.getPointCode());
if(ObjectUtils.isEmpty(vo)) {
return CommonResponseUtil.failure("該點位不存在");
}
if ("yc".equals(vo.getPointType())) {
return CommonResponseUtil.failure("該點位為遙測點位");
}
vo.setValue(point.getValue());
// ConfigVo config = confService.getServerByChannleNoId(vo.getChannelNo());
Collection<Session> c = SessionManager.getInstance().getClients();
for (Session s : c) {
s.addSOE(vo);
s.addSEC(vo);
}
pointConfigService.updatePoint(vo);
return CommonResponseUtil.success(vo);
}
@ApiOperation(value = "触发变位", notes = "触发变位")
@RequestMapping(value = "/trigger/sec", method = RequestMethod.PUT)
@Authorization(ingore=true)
public CommonResponse triggerSEC(@RequestBody PointParam point) {
log.info(point.toString());
PointConfigVo vo = pointConfigService.findPointByPointCode(point.getPointCode());
if(ObjectUtils.isEmpty(vo)) {
return CommonResponseUtil.failure("該點位不存在");
}
vo.setValue(point.getValue());
// ConfigVo config = confService.getServerByChannleNoId(vo.getChannelNo());
Collection<Session> c = SessionManager.getInstance().getClients();
for (Session s : c) {
s.addSEC(vo);
}
pointConfigService.updatePoint(vo);
return CommonResponseUtil.success(vo);
}
}
package com.yeejoin.amos.iec104.business.dao.repository;
import java.io.Serializable;
import java.util.List;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.NoRepositoryBean;
import org.springframework.data.repository.PagingAndSortingRepository;
/**
* 基础dao
*
* @param <T>
* @param <ID>
*/
@NoRepositoryBean
public interface BaseDao<T, ID extends Serializable> extends JpaRepository<T, ID>, CrudRepository<T, ID>,
PagingAndSortingRepository<T, ID>, JpaSpecificationExecutor<T> {
public default T getOneBySpecification(Specification<T> specification) {
List<T> list = findAll(specification);
if (list.isEmpty()) {
return null;
} else {
return list.get(0);
}
}
}
package com.yeejoin.amos.iec104.business.dao.repository;
import com.yeejoin.amos.connect.dao.entity.ClientListenVo;
import org.springframework.stereotype.Repository;
@Repository("iClientListenDao")
public interface IClientListenDao extends BaseDao<ClientListenVo, Long>{
}
package com.yeejoin.amos.iec104.business.dao.repository;
import java.util.List;
import com.yeejoin.amos.connect.dao.entity.PointConfigVo;
import org.apache.ibatis.annotations.Update;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;
@Repository("iPointConfigDao")
public interface IPointConfigDao extends BaseDao<PointConfigVo, Long> {
List<PointConfigVo> findAllByChannelNoAndPointType(String channelNo, String pointType);
@Update(value="delete from PointConfigVo where channelNo=?1")
void deleteAllByChannelNo(String channelNo);
@Query(value="select pointClassify from PointConfigVo where channelNo=?1 group by pointClassify")
List<String> getYcPointType(String channelNo);
@Query(value="select new com.yeejoin.amos.connect.dao.entity.PointConfigVo(p.id, p.commonAddress, p.originatorAddress, p.pointType, p.pointClassify, p.invalid, p.channelNo, p.name, p.pointCode ) from PointConfigVo p , ConfigVo c where p.channelNo=c.channelNo and c.serviceId=?1 and p.originatorAddress=?2 and p.pointClassify=?3")
PointConfigVo findOneByServicesIdAndInfoAddress(String serviceId, int address, String pointType);
PointConfigVo findOneByPointCode(String pointCode);
}
package com.yeejoin.amos.iec104.business.dao.repository;
import java.util.List;
import com.yeejoin.amos.connect.dao.entity.ConfigVo;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;
@Repository("iServiceConfDao")
public interface IServiceConfDao extends BaseDao<ConfigVo, Long>{
List<ConfigVo> findAllByServiceType(String serviceType);
ConfigVo findOneByServiceTypeAndPort(String serviceType, String port);
ConfigVo findOneByServiceTypeAndServiceId(String serviceType, String serverId);
@Query(value="select max(id) from ConfigVo")
String findMaxId();
ConfigVo findOneByServiceId(String serviceId);
}
package com.yeejoin.amos.iec104.business.entity.mybatis;
import java.util.Date;
public class RecData {
private int commonAddress;
private int informationAddress;
private String value;
private int DataType;
private Date createdTime;
private Date occurTime;
private String quality;
private int soe;
private long equitpmentPointId;
private String equitpmentPointName;
private long equitmentId;
private String equitmentName;
private String pointUnit;
private int isBlocked;
private int isSubstituted;
private int isNotTopical;
private int isInvalid;
private int isOverflow;
private String type;
private String serverId;
private String pointCode;
public RecData() {};
public RecData(String serverId) {
this.serverId = serverId;
}
public String getPointCode() {
return pointCode;
}
public void setPointCode(String pointCode) {
this.pointCode = pointCode;
}
public String getServerId() {
return serverId;
}
public void setServerId(String serverId) {
this.serverId = serverId;
}
public int getCommonAddress() {
return commonAddress;
}
public void setCommonAddress(int commonAddress) {
this.commonAddress = commonAddress;
}
public int getInformationAddress() {
return informationAddress;
}
public void setInformationAddress(int informationAddress) {
this.informationAddress = informationAddress;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public int getDataType() {
return DataType;
}
public void setDataType(int dataType) {
DataType = dataType;
}
public Date getCreatedTime() {
return createdTime;
}
public void setCreatedTime(Date createdTime) {
this.createdTime = createdTime;
}
public Date getOccurTime() {
return occurTime;
}
public void setOccurTime(Date occurTime) {
this.occurTime = occurTime;
}
public String getQuality() {
return quality;
}
public void setQuality(String quality) {
this.quality = quality;
}
public int getSoe() {
return soe;
}
public void setSoe(int soe) {
this.soe = soe;
}
public long getEquitpmentPointId() {
return equitpmentPointId;
}
public void setEquitpmentPointId(long equitpmentPointId) {
this.equitpmentPointId = equitpmentPointId;
}
public String getEquitpmentPointName() {
return equitpmentPointName;
}
public void setEquitpmentPointName(String equitpmentPointName) {
this.equitpmentPointName = equitpmentPointName;
}
public long getEquitmentId() {
return equitmentId;
}
public void setEquitmentId(long equitmentId) {
this.equitmentId = equitmentId;
}
public int getIsBlocked() {
return isBlocked;
}
public void setIsBlocked(int isBlocked) {
this.isBlocked = isBlocked;
}
public int getIsSubstituted() {
return isSubstituted;
}
public void setIsSubstituted(int isSubstituted) {
this.isSubstituted = isSubstituted;
}
public int getIsNotTopical() {
return isNotTopical;
}
public void setIsNotTopical(int isNotTopical) {
this.isNotTopical = isNotTopical;
}
public int getIsInvalid() {
return isInvalid;
}
public void setIsInvalid(int isInvalid) {
this.isInvalid = isInvalid;
}
public int getIsOverflow() {
return isOverflow;
}
public void setIsOverflow(int isOverflow) {
this.isOverflow = isOverflow;
}
public String getPointUnit() {
return pointUnit;
}
public void setPointUnit(String pointUnit) {
this.pointUnit = pointUnit;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
@Override
public String toString() {
return "RecData [commonAddress=" + commonAddress + ", informationAddress=" + informationAddress + ", value="
+ value + ", DataType=" + DataType + ", createdTime=" + createdTime + ", occurTime=" + occurTime
+ ", quality=" + quality + ", soe=" + soe + ", equitpmentPointId=" + equitpmentPointId
+ ", equitpmentPointName=" + equitpmentPointName + ", equitmentId=" + equitmentId + ", pointUnit="
+ pointUnit + ", isBlocked=" + isBlocked + ", isSubstituted=" + isSubstituted + ", isNotTopical="
+ isNotTopical + ", isInvalid=" + isInvalid + ", isOverflow=" + isOverflow + ", type=" + type + "]";
}
public String getEquitmentName() {
return equitmentName;
}
public void setEquitmentName(String equitmentName) {
this.equitmentName = equitmentName;
}
}
package com.yeejoin.amos.iec104.business.param;
public class AlarmParam {
private String informationAddress; //转发码
private int soe;
private String state; // 值
private String serviceId; //服务ID
private int isInvalid; // 是否有效
private String pointCode;
public int getSoe() {
return soe;
}
public void setSoe(int soe) {
this.soe = soe;
}
public String getPointCode() {
return pointCode;
}
public void setPointCode(String pointCode) {
this.pointCode = pointCode;
}
public String getState() {
return state;
}
public String getInformationAddress() {
return informationAddress;
}
public void setInformationAddress(String informationAddress) {
this.informationAddress = informationAddress;
}
public void setState(String state) {
this.state = state;
}
public String getServiceId() {
return serviceId;
}
public void setServiceId(String serviceId) {
this.serviceId = serviceId;
}
public int getIsInvalid() {
return isInvalid;
}
public void setIsInvalid(int isInvalid) {
this.isInvalid = isInvalid;
}
@Override
public String toString() {
return "AlarmParam [informationAddress=" + informationAddress + ", soe=" + soe + ", state=" + state
+ ", serviceId=" + serviceId + ", isInvalid=" + isInvalid + ", pointCode=" + pointCode + "]";
}
}
package com.yeejoin.amos.iec104.business.param;
public class ClientParam {
private String name;
private String ip;
private String port;
private String commonAddress;
private String serviceType;
private String serviceId;
public String getIp() {
return ip;
}
public void setIp(String ip) {
this.ip = ip;
}
public String getPort() {
return port;
}
public void setPort(String port) {
this.port = port;
}
public String getCommonAddress() {
return commonAddress;
}
public void setCommonAddress(String commonAddress) {
this.commonAddress = commonAddress;
}
public String getServiceType() {
return serviceType;
}
public void setServiceType(String serviceType) {
this.serviceType = serviceType;
}
public String getServiceId() {
return serviceId;
}
public void setServiceId(String serviceId) {
this.serviceId = serviceId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
package com.yeejoin.amos.iec104.business.param;
public class PacketParam {
private String type;
private String date;
private String conent;
private String serviceId;
private String packateType;
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public String getConent() {
return conent;
}
public void setConent(String conent) {
this.conent = conent;
}
public String getServiceId() {
return serviceId;
}
public void setServiceId(String serviceId) {
this.serviceId = serviceId;
}
public String getPackateType() {
return packateType;
}
public void setPackateType(String packateType) {
this.packateType = packateType;
}
}
package com.yeejoin.amos.iec104.business.param;
public class PointParam {
private String pointCode;
private String value;
public String getPointCode() {
return pointCode;
}
public void setPointCode(String pointCode) {
this.pointCode = pointCode;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
@Override
public String toString() {
return "PointParam [pointCode=" + pointCode + ", value=" + value + "]";
}
}
package com.yeejoin.amos.iec104.business.service.impl;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import com.yeejoin.amos.connect.dao.entity.ClientListenVo;
import com.yeejoin.amos.connect.dao.entity.ConfigVo;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import org.springframework.web.client.RestTemplate;
import com.yeejoin.amos.iec104.business.dao.repository.IClientListenDao;
import com.yeejoin.amos.iec104.business.dao.repository.IServiceConfDao;
import com.yeejoin.amos.iec104.business.param.AlarmParam;
import com.yeejoin.amos.iec104.business.service.intfc.IClientListenService;
@Service
public class ClientListenServiceImpl implements IClientListenService {
@Autowired
IClientListenDao iClientListenDao;
@Autowired
private IServiceConfDao iServiceConfDao;
@Override
@Transactional
public void del(Long id) {
iClientListenDao.delete(id);
}
@Override
@Transactional
public void add(ClientListenVo vo) {
iClientListenDao.save(vo);
}
@Override
public ClientListenVo findById(Long id) {
return iClientListenDao.findOne(id);
}
@Override
public void edit(ClientListenVo vo) {
}
@Override
public ClientListenVo findOne(ClientListenVo vo) {
return iClientListenDao.findOne(getSpecification(vo));
}
@Override
public List<ClientListenVo> findAll(ClientListenVo vo) {
return iClientListenDao.findAll(getSpecification(vo));
}
@Override
public void sendDatas(String dataType, LinkedList<AlarmParam> params) {
List<ConfigVo> clinets = iServiceConfDao.findAllByServiceType("IEC_SERVER");
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
for (ConfigVo c : clinets) {
HashMap<String, Object> param = new HashMap<>();
param.put("dataType", dataType);
param.put("channleNo", c.getChannelNo());
List<ClientListenVo> clientList = iClientListenDao.findAll(getSpecification(param));
for (ClientListenVo vo : clientList) {
if (ObjectUtils.isEmpty(vo.getUrl())) {
continue;
}
LinkedList<AlarmParam> list = filter(params, (p) -> p.getServiceId().equals(c.getServiceId()));
HttpEntity<LinkedList<AlarmParam>> request = new HttpEntity<>(list, headers);
try {
restTemplate.postForEntity( vo.getUrl(), request , String.class );
} catch (Exception e) {
}
}
}
}
public static LinkedList<AlarmParam> filter(List<AlarmParam> clints, java.util.function.Predicate<AlarmParam> condition) {
LinkedList<AlarmParam> results = new LinkedList<AlarmParam>();
for (AlarmParam c : clints) {
if(condition.test(c)) {
results.add(c);
}
}
return results;
}
@Override
public void sendData(String dataType, String channelNo, AlarmParam params) {
RestTemplate restTemplate = new RestTemplate();
HashMap<String, Object> param = new HashMap<>();
param.put("dataType", dataType);
param.put("channleNo", channelNo);
List<ClientListenVo> clientList = iClientListenDao.findAll(getSpecification(param));
for (ClientListenVo vo : clientList) {
if (ObjectUtils.isEmpty(vo.getUrl())) {
continue;
}
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
HttpEntity<AlarmParam> request = new HttpEntity<>(params, headers);
try {
Logger.getLogger(this.getClass()).debug("send "+dataType+" data to " + vo.getUrl() + " . param is" + params.toString());
restTemplate.postForEntity( vo.getUrl(), request , String.class );
// restTemplate.postForEntity( "http://172.16.10.183:8083/api/risksource/data/fireqeuiment/soe", request , String.class );
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 根据任务id构建查询任务回复信息查询条件
* @param
* @return Specification
*/
private Specification getSpecification(ClientListenVo vo) {
return new Specification<ClientListenVo>() { // 构建查询条件
@Override
public Predicate toPredicate(Root<ClientListenVo> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
List<Predicate> predicate = new ArrayList<>();
if (!ObjectUtils.isEmpty(vo.getChannleNo())) {
predicate.add(cb.equal(root.get("channleNo").as(String.class), vo.getChannleNo()));
}
if (!ObjectUtils.isEmpty(vo.getDataType())) {
predicate.add(cb.equal(root.get("dataType").as(String.class), vo.getDataType()));
}
if (!ObjectUtils.isEmpty(vo.getUrl())) {
predicate.add(cb.equal(root.get("url").as(String.class), vo.getUrl()));
}
Predicate[] pre = new Predicate[predicate.size()];
return query.where(predicate.toArray(pre)).getRestriction();
}
};
}
private Specification getSpecification(Map<String, Object> param) {
return new Specification<ClientListenVo>() { // 构建查询条件
@Override
public Predicate toPredicate(Root<ClientListenVo> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
List<Predicate> predicate = new ArrayList<>();
for (String key: param.keySet()) {
predicate.add(cb.equal(root.get(key).as(String.class), param.get(key)+""));
}
Predicate[] pre = new Predicate[predicate.size()];
return query.where(predicate.toArray(pre)).getRestriction();
}
};
}
@Override
public List<ClientListenVo> getDataByServiceId(String serviceId) {
ConfigVo vo = iServiceConfDao.findOneByServiceId(serviceId);
HashMap<String, Object> param = new HashMap<>();
param.put("channleNo", vo.getChannelNo());
return iClientListenDao.findAll(getSpecification(param));
}
}
package com.yeejoin.amos.iec104.business.service.impl;
import java.util.List;
import com.yeejoin.amos.connect.dao.entity.ConfigVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.yeejoin.amos.iec104.business.dao.repository.IServiceConfDao;
import com.yeejoin.amos.iec104.business.service.intfc.IConfService;
@Service
public class ConfServiceImpl implements IConfService {
@Autowired
private IServiceConfDao iServiceConfDao;
@Override
public void add(ConfigVo vo) {
iServiceConfDao.save(vo);
}
@Override
public void delete(Long id) {
iServiceConfDao.delete(id);
}
@Override
public List<ConfigVo> getServerByType(String type) {
return iServiceConfDao.findAllByServiceType(type);
}
@Override
public void updateServer(ConfigVo vo) {
iServiceConfDao.save(vo);
}
@Override
public ConfigVo getServerByPort(String port) {
return iServiceConfDao.findOneByServiceTypeAndPort("IEC_CLIENT",port);
}
@Override
public ConfigVo getServerByTypeAndServiceId(String type, String serverId) {
return iServiceConfDao.findOneByServiceTypeAndServiceId(type,serverId);
}
@Override
public String getMaxNo() {
return iServiceConfDao.findMaxId();
}
@Override
public ConfigVo getServerByServiceId(String serviceId) {
return iServiceConfDao.findOneByServiceId(serviceId);
}
@Override
public ConfigVo getServerById(Long id) {
return iServiceConfDao.findOne(id);
}
@Override
public ConfigVo findById(Long id) {
return iServiceConfDao.findOne(id);
}
@Override
public ConfigVo getServerByChannleNoId(String channelNo) {
// TODO Auto-generated method stub
return null;
}
}
package com.yeejoin.amos.iec104.business.service.impl;
import java.util.HashMap;
import java.util.List;
import javax.annotation.PostConstruct;
import com.yeejoin.amos.connect.dao.entity.PointConfigVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.yeejoin.amos.iec104.business.dao.repository.IPointConfigDao;
import com.yeejoin.amos.iec104.business.service.intfc.IPointConfigService;
@Service
public class PointConfigServiceImpl implements IPointConfigService{
@Autowired
private IPointConfigDao iPointConfigDao;
@Autowired
private RedisTemplate redisTemplate;
// @Override
// public List<PointConfigVo> getAllPointData(String channelNo) {
// return iPointConfigDao.findAllByChannelNo(channelNo);
// }
@Override
public List<PointConfigVo> getAllYXPointData(String channelNo) {
return iPointConfigDao.findAllByChannelNoAndPointType(channelNo, "yx");
}
@Override
public List<PointConfigVo> getAllYCPointData(String channelNo) {
return iPointConfigDao.findAllByChannelNoAndPointType(channelNo, "yc");
}
@Override
@Transactional
public void save(List<PointConfigVo> list) {
iPointConfigDao.save(list);
}
@Override
@Transactional
public void deleteByChannelNo(String channelNo) {
iPointConfigDao.deleteAllByChannelNo(channelNo);
}
@Override
public List<String> getYcPointType(String channelNo) {
return iPointConfigDao.getYcPointType(channelNo);
}
@Override
public PointConfigVo findByServicesIdAndInfoAddress(String serviceId, int address) {
String pointType = "";
if (address < 0x4000) {
pointType = "yx";
} else {
pointType = "yc";
address = address - 0x4000;
}
Pageable pageable = new PageRequest(0, 1);
return findPointfromRedis(serviceId+pointType+address);
// return iPointConfigDao.findOneByServicesIdAndInfoAddress(serviceId, address, pointType);
}
@Override
@PostConstruct
public void loadRedisData() {
HashMap<String, PointConfigVo> map = new HashMap<String, PointConfigVo>();
long count = iPointConfigDao.count();
for (int i = 0; i < (count/100000 + 1); i++) {
//分页信息
Pageable pageable = new PageRequest(i, 100000*(i+1));
iPointConfigDao.findAll().stream().forEach((PointConfigVo v) -> {
map.put(v.getChannelNo().replace("N", "S") + v.getPointType() +v.getOriginatorAddress(), v);
});
redisTemplate.opsForHash().putAll("pointConfig", map);
}
}
@Override
public PointConfigVo findPointfromRedis(String key) {
return (PointConfigVo) redisTemplate.opsForHash().get("pointConfig", key);
}
@Override
public PointConfigVo findPointByPointCode(String pointCode) {
return iPointConfigDao.findOneByPointCode(pointCode);
}
@Override
public void updatePoint(PointConfigVo vo) {
String key = vo.getChannelNo().replace("N", "S") + vo.getPointType() +vo.getOriginatorAddress();
redisTemplate.opsForHash().put("pointConfig", key, vo);
iPointConfigDao.save(vo);
}
}
package com.yeejoin.amos.iec104.business.service.intfc;
import java.util.LinkedList;
import java.util.List;
import com.yeejoin.amos.connect.dao.entity.ClientListenVo;
import com.yeejoin.amos.iec104.business.param.AlarmParam;
public interface IClientListenService {
public void del(Long id);
public void add(ClientListenVo vo);
public ClientListenVo findById(Long id);
public void edit(ClientListenVo vo);
public ClientListenVo findOne(ClientListenVo vo);
public List<ClientListenVo> findAll(ClientListenVo vo);
public void sendDatas(String dataType, LinkedList<AlarmParam> params);
public void sendData(String dataType, String channelNo,AlarmParam params);
public List<ClientListenVo> getDataByServiceId(String serviceId);
}
package com.yeejoin.amos.iec104.business.service.intfc;
import com.yeejoin.amos.connect.dao.entity.ConfigVo;
import java.util.List;
public interface IConfService {
public void add(ConfigVo vo);
public void delete(Long id);
public List<ConfigVo> getServerByType(String type);
public void updateServer(ConfigVo vo);
public ConfigVo getServerByPort(String port);
public ConfigVo getServerByTypeAndServiceId(String string, String serverId);
public String getMaxNo();
public ConfigVo getServerByServiceId(String serviceId);
public ConfigVo getServerById(Long id);
public ConfigVo findById(Long id);
public ConfigVo getServerByChannleNoId(String channelNo);
}
package com.yeejoin.amos.iec104.business.service.intfc;
import com.yeejoin.amos.connect.dao.entity.PointConfigVo;
import java.util.List;
public interface IPointConfigService {
// public List<PointConfigVo> getAllPointData(String channelNo);
public List<PointConfigVo> getAllYXPointData(String channelNo);
public List<PointConfigVo> getAllYCPointData(String channelNo);
public void save(List<PointConfigVo> list);
public void deleteByChannelNo(String channelNo);
public List<String> getYcPointType(String channelNo);
public PointConfigVo findByServicesIdAndInfoAddress(String serviceId, int address);
public void loadRedisData();
public PointConfigVo findPointfromRedis(String key);
public PointConfigVo findPointByPointCode(String pointCode);
public void updatePoint(PointConfigVo vo);
}
package com.yeejoin.amos.iec104.business.service.intfc;
import java.util.List;
public interface IPointService {
void noticePointChange(List<Long> ids);
void noticePointChangeTest();
void syncPointStatus();
}
package com.yeejoin.amos.iec104.context;
import java.lang.reflect.Method;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
@Configuration
@EnableCaching
public class CacheConfig extends CachingConfigurerSupport {
@Value("${spring.redis.host}")
private String host;
@Value("${spring.redis.port}")
private int port;
@Value("${spring.redis.timeout}")
private int timeout;
@Value("${spring.redis.database}")
private int database;
@Value("${spring.redis.password}")
private String password;
/**
* 键的生成策略
* @return
* 规则:目标类名称+方法名+参数名
*/
@Bean
public KeyGenerator wiselyKeyGenerator() {
return new KeyGenerator() {
@Override
public Object generate(Object target, Method method, Object... params) {
StringBuilder sb = new StringBuilder();
sb.append(target.getClass().getName());
sb.append(method.getName());
for (Object obj : params) {
sb.append(obj.toString());
}
return sb.toString();
}
};
}
@Bean
public JedisConnectionFactory redisConnectionFactory() {
JedisConnectionFactory factory = new JedisConnectionFactory();
factory.setHostName(host);
factory.setPort(port);
factory.setTimeout(timeout);
factory.setDatabase(database);
factory.setPassword(password);
return factory;
}
/**
* 配置CacheManager 管理cache
* @param redisTemplate
* @return
*/
@Bean
public CacheManager cacheManager(RedisTemplate redisTemplate) {
RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate);
cacheManager.setDefaultExpiration(60*60); // 设置key-value超时时间
return cacheManager;
}
@Bean
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(connectionFactory);
//使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值
Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper mapper = new ObjectMapper();
mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
serializer.setObjectMapper(mapper);
template.setValueSerializer(serializer);
//使用StringRedisSerializer来序列化和反序列化redis的key值
template.setKeySerializer(new StringRedisSerializer());
template.afterPropertiesSet();
return template;
}
}
/**
*
*/
package com.yeejoin.amos.iec104.context;
import org.apache.log4j.Logger;
import org.springframework.context.ApplicationContext;
import com.yeejoin.amos.iec104.business.constants.IEC104Constant;
/**
* iot-spring上下文
*
* @author as-youjun
*
*/
public class FireAutoIntfContext {
/**
* 实例
*/
private static FireAutoIntfContext instance;
/**
* spring上下文
*/
private ApplicationContext applicationContext;
/**
* 构造方法
*/
private FireAutoIntfContext() {
Logger.getLogger(this.getClass()).debug(IEC104Constant.CONSTRUCTOR);
}
/**
* 获取单例
*
* @return
*/
public static synchronized FireAutoIntfContext getInstance() {
if (instance == null) {
instance = new FireAutoIntfContext();
}
return instance;
}
/**
* 设置上下文
*
* @param applicationContext
*/
public void setApplicationContext(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
/**
* 获取上下文
*
* @param beanName
* @return
*/
public Object getBean(String beanName) {
return applicationContext.getBean(beanName);
}
/**
* 获取上下文
*
* @param requiredType
* @return
*/
public Object getBean(Class<?> requiredType) {
return applicationContext.getBean(requiredType);
}
}
package com.yeejoin.amos.iec104.context;
import javax.annotation.PostConstruct;
import org.springframework.stereotype.Component;
import com.yeejoin.amos.iec104.core.util.DateUtil;
import com.yeejoin.amos.op.core.entity.BusinessEntity;
import com.yeejoin.amos.op.core.entity.handler.EntityHandler;
import com.yeejoin.amos.op.core.entity.handler.EntityListener;
import com.yeejoin.amos.security.context.CurrentAuthentication;
/**
*
* <pre>
* 实体变化
* </pre>
*
* @author as-chenjiajun
* @version $Id: FireAutoIntfEntityHandler.java, v 0.1 2018年5月29日 下午3:42:41 as-chenjiajun Exp $
*/
@Component
public class FireAutoIntfEntityHandler extends EntityHandler
{
@PostConstruct
private void init()
{
EntityListener.addModelHandler(this);
}
public void prePersist(BusinessEntity model)
{
model.setCreateUser(CurrentAuthentication.getAuthenticatedUserId());
model.setCreateDate(DateUtil.getCurrentDate());
}
public void preUpdate(BusinessEntity model)
{
model.setUpdateUser(CurrentAuthentication.getAuthenticatedUserId());
model.setUpdateDate(DateUtil.getCurrentDate());
}
}
package com.yeejoin.amos.iec104.context;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
@Component
public class LoadDataUtil implements CommandLineRunner{
@Override
public void run(String... arg0) throws Exception {
}
}
package com.yeejoin.amos.iec104.context;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
//@Configuration
//@AutoConfigureAfter(RedisAutoConfiguration.class)
public class RedisConfig {
// @Bean
// @SuppressWarnings("all")
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
template.setConnectionFactory(factory);
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
// key采用String的序列化方式
template.setKeySerializer(stringRedisSerializer);
// hash的key也采用String的序列化方式
template.setHashKeySerializer(stringRedisSerializer);
// value序列化方式采用jackson
template.setValueSerializer(jackson2JsonRedisSerializer);
// hash的value序列化方式采用jackson
template.setHashValueSerializer(jackson2JsonRedisSerializer);
template.afterPropertiesSet();
return template;
}
}
package com.yeejoin.amos.iec104.core.common.datastructure;
import java.util.List;
/**
*
* <pre>
* 树节点
* </pre>
*
* @author as-chenjiajun
* @version $Id: TreeNode.java, v 0.1 2018年3月8日 下午5:36:46 as-chenjiajun Exp $
*/
public class TreeNode
{
//数据库数据ID
private Long sourceId;
//界面key
private String key;
//界面父节点key
private String parentKey;
//显示名称
private String title;
//子节点
private List<TreeNode> children;
//值
private String value;
public TreeNode(String key, String title, String parentKey)
{
this.key = key;
this.title = title;
this.parentKey = parentKey;
this.value = title;
}
public TreeNode(String key, String title, TreeNode parent)
{
this.key = key;
this.title = title;
this.parentKey = parent.getParentKey();
this.value = title;
}
public String getKey()
{
return key;
}
public void setKey(String key)
{
this.key = key;
}
public String getParentKey()
{
return parentKey;
}
public void setParentKey(String parentKey)
{
this.parentKey = parentKey;
}
public String getTitle()
{
return title;
}
public void setTitle(String title)
{
this.title = title;
}
public List<TreeNode> getChildren()
{
return children;
}
public void setChildren(List<TreeNode> children)
{
this.children = children;
}
public Long getSourceId()
{
return sourceId;
}
public void setSourceId(Long sourceId)
{
this.sourceId = sourceId;
}
public String getValue()
{
return value;
}
public void setValue(String value)
{
this.value = value;
}
}
package com.yeejoin.amos.iec104.core.common.request;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
/**
*
* <pre>
* 分页实体
* </pre>
*
* @author as-chenjiajun
* @version $Id: CommonPageable.java, v 0.1 2016-12-14 上午10:42:44 as-chenjiajun
* Exp $
*/
public class CommonPageable implements Pageable {
/**
* 页号(大于等于0)
*/
protected int pageNumber = 0;
/**
* 每页大小(大于等于0)
*/
protected int pageSize = 10;
/**
* 起始索引
*/
protected int offset = 0;
/**
* 排序
*/
protected Sort sort = null;
public CommonPageable() {
this.pageNumber = 0;
this.pageSize = 10;
this.offset = pageSize * pageNumber;
}
public CommonPageable(int pageNumber, int pageSize) {
this.pageNumber = pageNumber;
this.pageSize = pageSize;
this.offset = pageSize * pageNumber;
}
public CommonPageable(int pageNumber, int pageSize, Sort sort) {
this.pageNumber = pageNumber;
this.pageSize = pageSize;
this.sort = sort;
this.offset = pageSize * pageNumber;
}
public int getPageNumber() {
return this.pageNumber;
}
public int getPageSize() {
return pageSize;
}
public int getOffset() {
offset = pageSize * pageNumber;
return offset;
}
public Sort getSort() {
return sort;
}
public Pageable next() {
return null;
}
public Pageable previousOrFirst() {
return null;
}
public Pageable first() {
return null;
}
public boolean hasPrevious() {
return false;
}
public void setPageNumber(int pageNumber) {
this.pageNumber = pageNumber;
}
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
public void setSort(Sort sort) {
this.sort = sort;
}
public void setOffset(int offset) {
this.offset = offset;
}
}
package com.yeejoin.amos.iec104.core.common.request;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
/**
*
* <pre>
* 公共请求对象
* </pre>
*
* @author as-shibaobao
* @version $Id: CommonRequest.java, v 0.1 2018年1月26日 上午10:59:19 as-shibaobao Exp $
*/
@ApiModel
public class CommonRequest {
/**
* 字段名称
*/
@ApiModelProperty(value="字段名称",required=true)
private String name;
/**
* 字段值
*/
@ApiModelProperty(value="字段值",required=true)
private Object value;
/**
* 查询类型
*/
@ApiModelProperty(value="查询类型",notes="空值时,默认为等于;其它类型按QueryOperatorEnum",required=false)
private String type;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Object getValue() {
return value;
}
public void setValue(Object value) {
this.value = value;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}
/**
* NewHeight.com Inc.
* Copyright (c) 2008-2010 All Rights Reserved.
*/
package com.yeejoin.amos.iec104.core.common.response;
import java.util.List;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
/**
* <pre>
* 分页数据
* </pre>
*
* @author as-youjun
* @version $Id: CompanyPage.java, v 0.1 2017年4月13日 上午11:35:25 as-youjun Exp $
*/
public final class CommonPage<T> extends PageImpl<T> {
/**
* <pre>
* uid
* </pre>
*/
private static final long serialVersionUID = -5533124806408380886L;
/**
*
*/
private String message;
/**
* 返回结果状态
*/
private String result;
public CommonPage(List<T> content, Pageable pageable, long total) {
super(content, pageable, total);
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public String getResult()
{
return result;
}
public void setResult(String result)
{
this.result = result;
}
}
package com.yeejoin.amos.iec104.core.enums;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang.enums.ValuedEnum;
/**
* 操作枚举
*
* @author as-youjun
*
*/
@SuppressWarnings("all")
public final class QueryOperatorEnum extends ValuedEnum {
private static final long serialVersionUID = -375127751242109017L;
public static final int LESS_VALUE = 1; // 小于
public static final int BIGGER_VALUE = 2; // 大于
public static final int EQUAL_VALUE = 3; // 等于
public static final int LESS_EQUAL_VALUE = 4; // 小于等于
public static final int BIGGER_EQUAL_VALUE = 5; // 大于等于
public static final int NOT_EQUAL_VALUE = 6; // 不等于
public static final int IN_VALUE = 7; // 包含
public static final int LIKE_VALUE = 8; // like
public static final int OR_VALUE = 9; // 或者
public static final int ORDER_VALUE = 10; // 排序
public static final int NOT_IN_VALUE = 11; // 不包含
public static final int IS_VALUE= 12; //是
public static final QueryOperatorEnum LESS = new QueryOperatorEnum("LESS", 1, "<");
public static final QueryOperatorEnum BIGGER = new QueryOperatorEnum("BIGGER", 2, ">");
public static final QueryOperatorEnum EQUAL = new QueryOperatorEnum("EQUAL", 3, "=");
public static final QueryOperatorEnum LESS_EQUAL = new QueryOperatorEnum("LESS_EQUAL", 4, "<=");
public static final QueryOperatorEnum BIGGER_EQUAL = new QueryOperatorEnum("BIGGER_EQUAL", 5, ">=");
public static final QueryOperatorEnum NOT_EQUAL = new QueryOperatorEnum("NOT_EQUAL", 6, "<>");
public static final QueryOperatorEnum IN = new QueryOperatorEnum("IN", 7, "IN");
public static final QueryOperatorEnum LIKE = new QueryOperatorEnum("LIKE", 8, "LIKE");
public static final QueryOperatorEnum OR = new QueryOperatorEnum("OR", 9, "OR");
public static final QueryOperatorEnum ORDER_BY = new QueryOperatorEnum("ORDER BY", 10, "ORDER BY");
public static final QueryOperatorEnum NOT_IN = new QueryOperatorEnum("NOT IN", 11, "NOT IN");
public static final QueryOperatorEnum IS = new QueryOperatorEnum("IS", 12, "IS");
public String condition;
public String getCondition() {
return condition;
}
public void setCondition(String condition) {
this.condition = condition;
}
protected QueryOperatorEnum(String arg0, int arg1, String condition) {
super(arg0, arg1);
this.condition = condition;
}
public static QueryOperatorEnum getEnum(String name) {
try {
return ((QueryOperatorEnum) getEnum(QueryOperatorEnum.class, name));
} catch (Exception ex) {
return null;
}
}
public static QueryOperatorEnum getEnum(int name) {
try {
return ((QueryOperatorEnum) getEnum(QueryOperatorEnum.class, name));
} catch (Exception ex) {
return null;
}
}
public static Map getMap() {
try {
return getEnumMap(QueryOperatorEnum.class);
} catch (Exception ex) {
return null;
}
}
public static List getList() {
try {
return getEnumList(QueryOperatorEnum.class);
} catch (Exception ex) {
return null;
}
}
public static Iterator iterator() {
try {
return iterator(QueryOperatorEnum.class);
} catch (Exception ex) {
return null;
}
}
}
package com.yeejoin.amos.iec104.core.listener;
import org.springframework.boot.context.embedded.EmbeddedServletContainerInitializedEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
/**
*
* <pre>
* 配置信息获取
* </pre>
*
* @author as-chenjiajun
* @version $Id: PortConfigListener.java, v 0.1 2018年3月14日 下午3:10:15 as-chenjiajun Exp $
*/
@Component
public class PortConfigListener implements ApplicationListener<EmbeddedServletContainerInitializedEvent>
{
/**
* 服务器端口号
*/
private int serverPort;
@Override
public void onApplicationEvent(
EmbeddedServletContainerInitializedEvent event)
{
this.serverPort = event.getEmbeddedServletContainer().getPort();
}
public int getServerPort()
{
return serverPort;
}
}
package com.yeejoin.amos.iec104.core.threadpool;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.apache.log4j.Logger;
import com.yeejoin.amos.iec104.business.constants.IEC104Constant;
/**
* 线程池
*/
public class AmosThreadPool {
/**
* 日志记录器
*/
private static final Logger logger = Logger
.getLogger(AmosThreadPool.class);
/**
* 单例
*/
private static AmosThreadPool instance;
/**
* 执行服务
*/
private static ExecutorService executorService;
/**
* 获取单例
*
* @return
*/
public static AmosThreadPool getInstance() {
if (instance == null) {
synchronized (AmosThreadPool.class) {
if (instance == null) {
instance = new AmosThreadPool();
}
}
}
return instance;
}
static {
executorService = Executors
.newFixedThreadPool(IEC104Constant.AMOS_THREAD_NUM);
}
/**
* 执行线程
*
* @param task
*/
public void execute(Runnable task) {
executorService.execute(task);
}
}
package com.yeejoin.amos.iec104.core.util;
import java.text.ParseException;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
/**
*
* <pre>
* 日期
* </pre>
*
* @author as-chenjiajun
* @version $Id: DateUtil.java, v 0.1 2018年1月29日 下午5:08:40 as-chenjiajun Exp $
*/
public class DateUtil
{
private static String LONG_PATTERN = "yyyy-MM-dd HH:mm:ss";
private static String MID_PATTERN = "yyyy-MM-dd HH:mm";
private static String SHORT_PATTERN = "yyyy-MM-dd";
public static long THREE_DAY_MILLSEC = 259200000L;
public static long ONE_DAY_MILLSEC = 86400000L;
public static long ONE_HOUR_MILLSEC = 3600000L;
public static long THREE_HOURS_MILLSEC = 10800000L;
public static long TWELVE_HOURS_MILLSEC = 43200000L;
public static Date EMPTY_DATE = null;
static
{
Calendar calendar = Calendar.getInstance();
calendar.set(9999, 0, 0);
EMPTY_DATE = calendar.getTime();
}
/**
*
* <pre>
* 获取当前北京时间
* </pre>
*
* @return
*/
public static Date getCurrentDate()
{
return getCurrentCalendar().getTime();
}
public static String getLongCurrentDate()
{
return new SimpleDateFormat(LONG_PATTERN)
.format(getCurrentCalendar().getTime());
}
public static String getLongDate(Date date)
{
if (null == date)
return getLongCurrentDate();
else
return new SimpleDateFormat(LONG_PATTERN).format(date);
}
public static String getLongDate(long value)
{
return new SimpleDateFormat(LONG_PATTERN).format(new Date(value));
}
public static String getShortCurrentDate()
{
return new SimpleDateFormat(SHORT_PATTERN).format(new Date());
}
public static String getShortDate(Date date)
{
if (null == date)
return getShortCurrentDate();
else
return new SimpleDateFormat(SHORT_PATTERN).format(date);
}
public static String getShortDate(long value)
{
return new SimpleDateFormat(SHORT_PATTERN).format(new Date(value));
}
public static Date getShortCurrentDate(String shortDateStr) throws ParseException
{
return new SimpleDateFormat(SHORT_PATTERN).parse(shortDateStr);
}
public static Date getLongDate(String longDateStr) throws ParseException
{
return new SimpleDateFormat(LONG_PATTERN).parse(longDateStr);
}
public static String getMidCurrentDate()
{
return new SimpleDateFormat(MID_PATTERN).format(new Date());
}
public static String getMidDate(Date date)
{
if (null == date)
return getMidCurrentDate();
else
return new SimpleDateFormat(MID_PATTERN).format(new Date());
}
public static String getMidDate(long value)
{
return new SimpleDateFormat(MID_PATTERN).format(new Date(value));
}
public static Date str2Date(String strDate, String dateFormat)
{
SimpleDateFormat formatter = new SimpleDateFormat(dateFormat);
ParsePosition pos = new ParsePosition(0);
Date strtodate = formatter.parse(strDate, pos);
return strtodate;
}
public static int getYear(Date date)
{
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
int year = calendar.get(Calendar.YEAR);
return year;
}
public static int getMonth(Date date)
{
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
int month = calendar.get(Calendar.MONTH) + 1;
return month;
}
public static int getDay(Date date)
{
Calendar c = Calendar.getInstance();
c.setTime(date);
int day = c.get(Calendar.DATE);
return day;
}
public static int getHour(Date date)
{
Calendar c = Calendar.getInstance();
c.setTime(date);
int hour = c.get(Calendar.HOUR_OF_DAY);
return hour;
}
public static int getMinite(Date date)
{
Calendar c = Calendar.getInstance();
c.setTime(date);
int minite = c.get(Calendar.MINUTE);
return minite;
}
/**
*
* <pre>
* 获取当前北京时间
* </pre>
*
* @return
*/
public static Calendar getCurrentCalendar()
{
TimeZone.setDefault(TimeZone.getTimeZone("Asia/Shanghai"));
return Calendar.getInstance();
}
/**
*
* <pre>
* 获取当前两个时间差
* </pre>
*
* @return
*/
public static String getTimeDifference(Date dateBefore, Date dateAfter )
{
long l=dateAfter.getTime()-dateBefore.getTime();
long day=l/(24*60*60*1000);
long hour=(l/(60*60*1000)-day*24);
long min=((l/(60*1000))-day*24*60-hour*60);
long s=(l/1000-day*24*60*60-hour*60*60-min*60);
return ""+day+"天"+hour+"小时"+min+"分"+s+"秒";
}
}
package com.yeejoin.amos.iec104.core.util;
import java.math.BigDecimal;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.springframework.util.Assert;
/**
* 字符串工具类
*
* @author as-youjun
*
*/
public class StringUtil {
private static Pattern NOT_ZERO_AT_THE_END = Pattern.compile("[1-9](\\d*[1-9])?");
private static Pattern numericPattern = Pattern.compile("-?[0-9]+\\.?[0-9]*");
/**
* 判断对象是否为空
*
* @param str
* @return
*/
public static boolean isNotEmpty(Object str) {
boolean flag = true;
if (str != null && !str.equals("")) {
if (str.toString().length() > 0) {
flag = true;
}
} else {
flag = false;
}
return flag;
}
/***************************************************************************
* repeat - 通过源字符串重复生成N次组成新的字符串。
*
* @param src
* - 源字符串 例如: 空格(" "), 星号("*"), "浙江" 等等...
* @param num
* - 重复生成次数
* @return 返回已生成的重复字符串
* @version 1.0 (2006.10.10) Wilson Lin
**************************************************************************/
public static String repeat(String src, int num) {
StringBuffer s = new StringBuffer();
for (int i = 0; i < num; i++)
s.append(src);
return s.toString();
}
/**
* 判断是否数字表示
*
* @param src
* 源字符串
* @return 是否数字的标志
*/
public static boolean isNumeric(String str) {
// 该正则表达式可以匹配所有的数字 包括负数
String bigStr;
try {
bigStr = new BigDecimal(str).toString();
} catch (Exception e) {
return false;// 异常 说明包含非数字。
}
Matcher isNum = numericPattern.matcher(bigStr); // matcher是全匹配
if (!isNum.matches()) {
return false;
}
return true;
}
public static int toInt(String s) {
if (s != null && !"".equals(s.trim())) {
try {
return Integer.parseInt(s);
} catch (Exception e) {
return 0;
}
}
return 0;
}
/**
* 截取前后都不是0的数字字符串
*
* 12010102 => 12010102 12010100 => 120101 ab1201100b => 12011
*
* @param str
* @return
*/
public static String delEndZero(String str) {
Matcher mat = NOT_ZERO_AT_THE_END.matcher(str);
boolean rs = mat.find();
if (rs) {
return mat.group(0);
}
return null;
}
/**
*
* <pre>
* 移除字符串后面的0
* </pre>
*
* @param s
* @return
*/
public static String removeSufixZero(String s) {
if (s == null) {
return "";
}
while (s.endsWith("0")) {
if (s.equals("0")) {
s = "";
break;
}
s = s.substring(0, s.length() - 1);
}
return s;
}
public static String transforCode(String code) {
if (code.endsWith("0000000")) {
code = code.substring(0, 1);
} else if (code.endsWith("000000")) {
code = code.substring(0, 2);
} else if (code.endsWith("0000")) {
code = code.substring(0, 4);
} else if (code.endsWith("00")) {
code = code.substring(0, 6);
}
return code;
}
/**
* 获取支队orgCode
*
* @param orgCode
* @return
*/
public static String getDetachmentOrgCode(String orgCode) {
Assert.notNull(orgCode, "组织结构orgCode不能为空!");
String[] codes = orgCode.split("\\*");
if (codes.length < 2) {
throw new IllegalArgumentException("组织结构orgCode为总队,不能获取支队orgCode!");
} else {
return codes[0] + "*" + codes[1];
}
}
}
package com.yeejoin.amos.iec104.core.util;
import java.util.ArrayList;
import java.util.List;
import com.yeejoin.amos.iec104.core.common.datastructure.TreeNode;
/**
*
* <pre>
* 树相关操作
* </pre>
*
* @author as-chenjiajun
* @version $Id: TreeUtil.java, v 0.1 2018年3月8日 下午5:37:36 as-chenjiajun Exp $
*/
public class TreeUtil
{
/**
*
* <pre>
* 两层循环实现建树
* </pre>
*
* @param treeNodes 传入的树节点列表
* @return
*/
public static List<TreeNode> bulid(List<TreeNode> treeNodes)
{
List<TreeNode> trees = new ArrayList<TreeNode>();
for (TreeNode treeNode : treeNodes)
{
if ("0".equals(treeNode.getParentKey()))
{
trees.add(treeNode);
}
for (TreeNode it : treeNodes)
{
if (it.getParentKey() == treeNode.getKey())
{
if (treeNode.getChildren() == null)
{
treeNode.setChildren(new ArrayList<TreeNode>());
}
treeNode.getChildren().add(it);
}
}
}
return trees;
}
/**
*
* <pre>
* 使用递归方法建树
* </pre>
*
* @param treeNodes
* @return
*/
public static List<TreeNode> buildByRecursive(List<TreeNode> treeNodes,String rootKey)
{
List<TreeNode> trees = new ArrayList<TreeNode>();
for (TreeNode treeNode : treeNodes)
{
if (rootKey.equals(treeNode.getParentKey()))
{
trees.add(findChildren(treeNode, treeNodes));
}
}
return trees;
}
/**
*
* <pre>
* 递归查找子节点
* </pre>
*
* @param treeNode
* @param treeNodes
* @return
*/
public static TreeNode findChildren(TreeNode treeNode,
List<TreeNode> treeNodes)
{
for (TreeNode it : treeNodes)
{
if (treeNode.getKey().equals(it.getParentKey()))
{
if (treeNode.getChildren() == null)
{
treeNode.setChildren(new ArrayList<TreeNode>());
}
treeNode.getChildren().add(findChildren(it, treeNodes));
}
}
return treeNode;
}
/**
*
* <pre>
* 搜索树
* </pre>
*
* @param treeNodes
* @param keyList 所有key值
* @return
*/
public static List<String> deepSearch(List<TreeNode> treeNodes,List<String> keyList)
{
List<String> currentList = new ArrayList<String>();
for (TreeNode treeNode : treeNodes)
{
currentList.add(treeNode.getKey());
if (treeNode.getChildren() != null)
{
currentList.addAll(deepSearch(treeNode.getChildren(),keyList));
}
}
return currentList;
}
}
package com.yeejoin.amos.iec104.core.websocket;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
/**
*
*/
package com.yeejoin.amos.iec104.entity;
/**
* 协议解决结果
*
* @author as-youjun
*
*/
public class ParseResult {
/**
* 状态:0表示失败,1表示成功
*/
private int status = 0;
/**
* 错误内容:只有当status=0时,errorMsg才会有内容
*/
private String errorMsg;
/**
* 结果数据
*/
private Object result;
/**
* @return the status
*/
public int getStatus() {
return status;
}
/**
* @param status
* the status to set
*/
public void setStatus(int status) {
this.status = status;
}
/**
* @return the errorMsg
*/
public String getErrorMsg() {
return errorMsg;
}
/**
* @param errorMsg
* the errorMsg to set
*/
public void setErrorMsg(String errorMsg) {
this.errorMsg = errorMsg;
}
/**
* @return the result
*/
public Object getResult() {
return result;
}
/**
* @param result
* the result to set
*/
public void setResult(Object result) {
this.result = result;
}
@Override
public String toString() {
return new StringBuilder().append("status=").append(status)
.append("result=").append(result).toString();
}
}
package com.yeejoin.amos.iec104.exception;
/**
*
* <pre>
* 自定义异常
* </pre>
*
* @author as-youjun
* @version $Id: YeeException.java, v 0.1 2017年7月18日 上午9:34:21 as-youjun Exp $
*/
public class YeeException extends RuntimeException {
/**
* <pre>
*
* </pre>
*/
private static final long serialVersionUID = -1963401137898098411L;
private int errorCode = 0;
public YeeException(int errorCode) {
this.errorCode = errorCode;
}
public YeeException(String message, int errorCode) {
super(message);
this.errorCode = errorCode;
}
public YeeException(String message) {
super(message);
}
public YeeException(String message, Throwable cause, int errorCode) {
super(message, cause);
this.errorCode = errorCode;
}
public YeeException(Throwable cause, int errorCode) {
super(cause);
this.errorCode = errorCode;
}
public YeeException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace,
int errorCode) {
super(message, cause, enableSuppression, writableStackTrace);
this.errorCode = errorCode;
}
/**
* Getter method for property <tt>errorCode</tt>.
*
* @return property value of errorCode
*/
public int getErrorCode() {
return errorCode;
}
/**
* Setter method for property <tt>errorCode</tt>.
*
* @param errorCode
* value to be assigned to property errorCode
*/
public void setErrorCode(int errorCode) {
this.errorCode = errorCode;
}
}
package com.yeejoin.amos.iec104.tcp;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import org.apache.log4j.Logger;
import org.springframework.util.ObjectUtils;
import com.yeejoin.amos.iec104.business.param.PacketParam;
import com.yeejoin.amos.iec104.tcp.entity.Apdu;
import com.yeejoin.amos.iec104.tcp.utils.ChangeUtils;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
public class IEC104Decoder extends ByteToMessageDecoder{
private SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss:SSS");
private String serviceId = "";
public IEC104Decoder(String serviceId) {
this.serviceId = serviceId;
}
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
in = in.markReaderIndex();
in = in.markWriterIndex();
byte[] dis = new byte[in.readableBytes()];
in.readBytes(dis);
in.resetReaderIndex();
in.resetWriterIndex();
Logger.getLogger(this.getClass()).debug("接收报文内容: " + ChangeUtils.toHexString(dis));
if (ObjectUtils.isEmpty(dis)) {
in.clear();
return;
}
if (in.isReadable()) {
int start = dis[0] & 0xff;
int len = dis[1] & 0xff;
if(start != 104 ){
in.readByte();
return;
}else if(len + 2 > in.readableBytes()){
return;
}
try {
Apdu apdu = new Apdu(in);
out.add(apdu);
} catch (Exception e) {
in.clear();
e.printStackTrace();
}
}
PacketParam param = new PacketParam();
param.setConent(ChangeUtils.toHexString(dis));
param.setDate(sdf.format(new Date()));
param.setType("接收");
param.setServiceId(serviceId);
WebSocketQueue.getInstance().add(param);
}
}
package com.yeejoin.amos.iec104.tcp;
import java.net.InetSocketAddress;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.apache.log4j.Logger;
import com.alibaba.fastjson.JSON;
import com.yeejoin.amos.iec104.business.param.PacketParam;
import com.yeejoin.amos.iec104.tcp.utils.ChangeUtils;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;
public class IEC104Encoder extends MessageToByteEncoder<String>{
private SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss:SSS");
private String serviceId = "";
public IEC104Encoder(String serviceId) {
this.serviceId = serviceId;
}
@Override
protected void encode(ChannelHandlerContext ctx, String msg, ByteBuf out) throws Exception {
InetSocketAddress socket = (InetSocketAddress) ctx.channel().remoteAddress();
String clientIp = socket.toString();
PacketParam param = new PacketParam();
param.setConent(msg);
param.setDate(sdf.format(new Date()));
param.setType("发送");
param.setServiceId(serviceId);
WebSocketQueue.getInstance().add(param);
Logger.getLogger(this.getClass()).debug("发送报文--->:" + msg.replace(" ", "") + " 到 --->" + clientIp);
out.writeBytes(ChangeUtils.hexStringToBytes(msg.replace(" ", "")));
}
}
package com.yeejoin.amos.iec104.tcp;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import javax.annotation.PostConstruct;
import com.yeejoin.amos.connect.dao.entity.ConfigVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import com.yeejoin.amos.iec104.business.dao.repository.IServiceConfDao;
import com.yeejoin.amos.iec104.tcp.client.IEC104ClientManager;
import com.yeejoin.amos.iec104.tcp.client.Init;
import com.yeejoin.amos.iec104.tcp.client.invoke.ApduQueue;
import com.yeejoin.amos.iec104.tcp.client.invoke.GeneralDataQueue;
import com.yeejoin.amos.iec104.tcp.client.invoke.RecDataQueue;
import com.yeejoin.amos.iec104.tcp.server.IEC104Server;
import com.yeejoin.amos.iec104.tcp.server.session.SessionManager;
import com.yeejoin.amos.op.core.util.ApplicationConfig;
@Component("tcpServer")
@Scope("singleton")
public class TcpServer {
@Autowired
private ApplicationConfig applicationConfig;
private static ConcurrentHashMap<Long, IEC104Server> servers = new ConcurrentHashMap<Long, IEC104Server>();
@Autowired
IEC104ClientManager iec104ClientManager;
SessionManager sessionManager = SessionManager.getInstance();
@Autowired
private IServiceConfDao iServiceConfDao;
@PostConstruct
public void start() {
WebSocketQueue.getInstance().start();
Init.start();
List<ConfigVo> list = iServiceConfDao.findAllByServiceType("IEC_CLIENT");
for (ConfigVo vo : list) {
IEC104Server iec104Server = new IEC104Server();
iec104Server.setPort(Integer.parseInt(vo.getPort()));
iec104Server.setApplicationConfig(applicationConfig);
iec104Server.start();
servers.put(vo.getId(), iec104Server);
}
iec104ClientManager.init();
ApduQueue.getInstance().start();
RecDataQueue.getInstance().start();
GeneralDataQueue.getInstance().start();
}
public void createIecService(Long id, String port) {
IEC104Server iec104Server = new IEC104Server();
iec104Server.setPort(Integer.parseInt(port));
iec104Server.setApplicationConfig(applicationConfig);
iec104Server.start();
servers.put(id, iec104Server);
}
public void closeIecService(Long id) {
IEC104Server iec104Server = servers.get(id);
iec104Server.close();
servers.remove(id);
}
}
package com.yeejoin.amos.iec104.tcp;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ScheduledExecutorService;
import org.apache.log4j.Logger;
import com.alibaba.fastjson.JSON;
import com.yeejoin.amos.iec104.business.param.PacketParam;
import com.yeejoin.amos.iec104.tcp.client.invoke.RecDataQueue;
import com.yeejoin.amos.iec104.tcp.entity.Apdu;
import com.yeejoin.amos.iec104.tcp.utils.ChangeUtils;
import com.yeejoin.amos.iec104.websocket.EquipmentWebsocket;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
public class WebSocketQueue {
private static final BlockingQueue<PacketParam> blockingQueue = new LinkedBlockingQueue<PacketParam>();
private volatile static WebSocketQueue instance = null;
ScheduledExecutorService service = null;
private WebSocketQueue() {
}
public static WebSocketQueue getInstance(){
//先检查实例是否存在,如果不存在才进入下面的同步块
if(instance == null){
//同步块,线程安全的创建实例
synchronized(RecDataQueue.class){
//再次检查实例是否存在,如果不存在才真的创建实例
if(instance == null){
instance = new WebSocketQueue();
}
}
}
return instance;
}
/**
* 启动apdu数据消费任务
*/
public void start() {
service = Executors.newSingleThreadScheduledExecutor();
// 第二个参数为首次执行的延时时间,第三个参数为定时执行的间隔时间
service.execute(task_runnable);
}
public void add(PacketParam packet) {
blockingQueue.add(packet);
}
Runnable task_runnable = new Runnable() {
public void run() {
while(true) {
try {
PacketParam data = blockingQueue.take();
byte[] conent = ChangeUtils.hexStringToBytes(data.getConent());
ByteBuf buf = Unpooled.buffer(conent.length);
buf.markReaderIndex();
buf.writeBytes(conent);
buf.resetReaderIndex();
// Logger.getLogger(this.getClass()).error("conent length is " + buf.readableBytes());
// Logger.getLogger(this.getClass()).error("buf can read length is " + buf.readableBytes());
if (buf.readableBytes() == conent.length) {
Apdu apdu = new Apdu(buf);
data.setPackateType(apdu.getApciType().name());
EquipmentWebsocket.sendInfo(JSON.toJSONString(data));
}
buf.clear();
buf = null;
} catch (Exception e) {
Logger.getLogger(this.getClass()).error(e.getMessage());
e.printStackTrace();
}
}
}
};
}
package com.yeejoin.amos.iec104.tcp.client;
import java.net.InetSocketAddress;
import java.util.Date;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
import org.apache.log4j.Logger;
import org.springframework.util.ObjectUtils;
import com.yeejoin.amos.iec104.tcp.client.invoke.ApduQueue;
import com.yeejoin.amos.iec104.tcp.entity.Apdu;
import com.yeejoin.amos.iec104.tcp.entity.ServerData;
import com.yeejoin.amos.iec104.tcp.utils.ChangeUtils;
import com.yeejoin.amos.iec104.tcp.utils.Constant;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelPromise;
import io.netty.channel.SimpleChannelInboundHandler;
public class ClientHandler extends SimpleChannelInboundHandler<Apdu>{
public IEC104Client client = null; //接收序号
private ChannelHandlerContext ctx;
private long recordTime = 0;
private boolean running = true;
private int MAX_INTERVAL_T3 = 10;
private int MAX_INTERVAL_T1 = 1000 * 30;
private int MAX_INTERVAL_T2 = 1000 * 3;
private int MAX_INTERVAL_T = 1000 * 60 * 5;
private boolean connetOk = false;
private boolean reviceIPackage = false;
private long lastTimeReviceI = 0;
private boolean startZZ = false;
private boolean startSystem = true;
private ScheduledExecutorService testService = null;
private ReentrantLock lock = new ReentrantLock(true);
private ReentrantLock zzlock = new ReentrantLock(true);
public ClientHandler(IEC104Client client) {
recordTime = new Date().getTime();
this.client = client;
}
@Override
protected void channelRead0(ChannelHandlerContext ctx, Apdu apdu) throws Exception {
try {
Date date = new Date();
this.recordTime = date.getTime();
ChannelPromise promise = ctx.newPromise();
if (apdu.getApciType() == Apdu.ApciType.I_FORMAT) {
// this.client.setSendSeqNum(apdu.getReceiveSeqNumber());
// this.client.setReceiveSeqNum(apdu.getSendSeqNumber());
if (!ObjectUtils.isEmpty(testService)) {
testService.shutdownNow();
testService = null;
}
this.lastTimeReviceI = this.recordTime;
reviceIPackage = true;
// 处理I命令
handleData(apdu);
} else if (apdu.getApciType() == Apdu.ApciType.S_FORMAT) {
// this.client.relase();
if (!ObjectUtils.isEmpty(testService)) {
testService.shutdownNow();
testService = null;
}
}else if (apdu.getApciType() == Apdu.ApciType.STARTDT_ACT) {
ctx.channel().writeAndFlush("68040B000000", promise);
Logger.getLogger(this.getClass()).debug("确认启动消息,U类型");
if (!ObjectUtils.isEmpty(testService)) {
testService.shutdownNow();
testService = null;
}
} else if (apdu.getApciType() == Apdu.ApciType.STOPDT_ACT) {
ctx.channel().writeAndFlush("680423000000", promise);
Logger.getLogger(this.getClass()).debug("确认停止消息,U类型");
if (!ObjectUtils.isEmpty(testService)) {
testService.shutdownNow();
testService = null;
}
connetOk = false;
} else if (apdu.getApciType() == Apdu.ApciType.TESTFR_ACT) {
ctx.channel().writeAndFlush("680483000000", promise);
Logger.getLogger(this.getClass()).debug("确认测试消息,U类型");
} else if (apdu.getApciType() == Apdu.ApciType.STARTDT_CON) {
Logger.getLogger(this.getClass()).debug("启动确认帧回复,U类型");
if (!ObjectUtils.isEmpty(startService)) {
startService.shutdownNow();
startService = null;
}
startZZ = true;
if (startSystem) {
ctx.channel().writeAndFlush("680443000000", promise);
}
startSystem = false;
connetOk = true;
} else if (apdu.getApciType() == Apdu.ApciType.TESTFR_CON) {
Logger.getLogger(this.getClass()).debug("确认测试消息回复,U类型");
if (startZZ) {
startZZ = false;
sendZzCommand();
}
} else{
Logger.getLogger(this.getClass()).debug("其它报文:" + apdu.getApciType());
if (!ObjectUtils.isEmpty(testService)) {
testService.shutdownNow();
testService = null;
}
}
}catch (Exception e){
e.printStackTrace();
Logger.getLogger(this.getClass()).debug("异常错误,"+ e);
}
}
private void handleData(Apdu apdu) {
if (apdu.getAsdu().getTypeId()== 100) {
return;
}
ServerData serverData = new ServerData();
serverData.setApdu(apdu);
serverData.setServerId(client.getClientId());
ApduQueue.getInstance().add(serverData);
}
private ScheduledExecutorService zzService = null;
private ScheduledExecutorService startService = null;
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
super.channelActive(ctx);
Runnable runnable = new Runnable() {
public void run() {
ctx.channel().writeAndFlush("680407000000");
}
};
startService = Executors.newSingleThreadScheduledExecutor();
// 第二个参数为首次执行的延时时间,第三个参数为定时执行的间隔时间
startService.scheduleAtFixedRate(runnable, Constant.Z_Z_INITIALDELAY, Constant.S_S_PREIOD, TimeUnit.SECONDS);
Date date = new Date();
this.recordTime = date.getTime();
if (!recordTimeThread.isAlive()) {
recordTimeThread.start();
}
this.ctx = ctx;
InetSocketAddress insocket = (InetSocketAddress) ctx.channel()
.remoteAddress();
String clientIP = insocket.getAddress().getHostAddress();
Logger.getLogger("channelActive 建立了TCP连接 --->" + clientIP);
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
super.channelInactive(ctx);
if (!ObjectUtils.isEmpty(startService)) {
startService.shutdownNow();
startService = null;
}
if (!ObjectUtils.isEmpty(zzService)) {
zzService.shutdownNow();
zzService = null;
}
if (recordTimeThread.isAlive()) {
running = false;
}
InetSocketAddress insocket = (InetSocketAddress) ctx.channel()
.remoteAddress();
String clientIP = insocket.getAddress().getHostAddress();
Logger.getLogger("channelActive 断开了TCP连接 --->" + clientIP);
// this.client.setReceiveSeqNum(0);
// this.client.setSendSeqNum(0);
this.client.closeChannel();
}
private void sendZzCommand() {
if (zzlock.tryLock()) {
if (!ObjectUtils.isEmpty(zzService)) {
zzlock.unlock();
return;
}
Runnable runnable = new Runnable() {
public void run() {
try {
boolean isSend = false;
do {
isSend = true;
if (connetOk) {
byte[] recNum = new byte[2];
// recNum[0] = (byte) (client.getReceiveSeqNum() << 1);
// recNum[1] = (byte) (client.getReceiveSeqNum() >> 7);
// String recStr = ChangeUtils.toHexString(recNum);
// byte[] sendNum = new byte[2];
// sendNum[0] = (byte) (client.getSendSeqNum() << 1);
// sendNum[1] = (byte) (client.getSendSeqNum() >> 7);
// client.setSendSeqNum(client.getSendSeqNum() + 1);
// String sendStr = ChangeUtils.toHexString(sendNum);
// String commonAddress = client.getCommonAddress();
// String zzPackate = "680E"+sendStr+recStr+"64010600"+commonAddress+"00000014";
// client.sendMessage(zzPackate.replace(" ", "").toUpperCase());
}
} while(!isSend);
} catch (Exception e) {
e.printStackTrace();
}
}
};
zzService = Executors.newSingleThreadScheduledExecutor();
// 第二个参数为首次执行的延时时间,第三个参数为定时执行的间隔时间
zzService.scheduleAtFixedRate(runnable, Constant.Z_Z_INITIALDELAY, Constant.Z_Z_PREIOD, TimeUnit.SECONDS);
zzlock.unlock();
}
}
public void startTest() {
boolean start = false;
do {
try {
if (lock.tryLock()) {
if (!ObjectUtils.isEmpty(testService)) {
lock.unlock();
return;
}
Runnable runnable = new Runnable() {
public void run() {
ctx.channel().writeAndFlush("680443000000");
}
};
testService = Executors.newSingleThreadScheduledExecutor();
// 第二个参数为首次执行的延时时间,第三个参数为定时执行的间隔时间
testService.scheduleAtFixedRate(runnable, Constant.Z_Z_INITIALDELAY, MAX_INTERVAL_T3, TimeUnit.SECONDS);
lock.unlock();
if ( start == false) {
start = true;
}
}
} catch (Exception e) {
}
} while(!start);
}
Thread recordTimeThread = new Thread(new Runnable() {
@Override
public void run() {
running = true;
while(running) {
long interval = (new Date().getTime() - recordTime);
long IInterval = 0;
if (lastTimeReviceI == 0) {
IInterval = 0;
} else {
IInterval = new Date().getTime() - lastTimeReviceI;
}
if (startSystem && interval >= MAX_INTERVAL_T1) {
ctx.disconnect();
}
if (interval >= MAX_INTERVAL_T) {
ctx.close();
}
if (!ObjectUtils.isEmpty(startService) && ObjectUtils.isEmpty(testService) && interval > MAX_INTERVAL_T3 * 1000) {
ctx.channel().writeAndFlush("680443000000");
startTest();
}
if (reviceIPackage && IInterval > MAX_INTERVAL_T2) {
// reviceIPackage = false;
// // 返回S确认命令
// String recStr = client.sendACKMessage();
// if (recStr == null) {
// reviceIPackage = true;
// } else {
// lastTimeReviceI = new Date().getTime();
// }
// Logger.getLogger(this.getClass()).debug("确认消息,S类型,下一条的接受序号:" + recStr);
}
}
}
});
}
package com.yeejoin.amos.iec104.tcp.client;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
import org.apache.log4j.Logger;
import org.springframework.util.ObjectUtils;
import com.yeejoin.amos.iec104.exception.YeeException;
import com.yeejoin.amos.iec104.tcp.IEC104Decoder;
import com.yeejoin.amos.iec104.tcp.IEC104Encoder;
import com.yeejoin.amos.iec104.tcp.utils.ChangeUtils;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.ChannelPromise;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.timeout.IdleStateHandler;
public class IEC104Client {
private final String host;
private final int port;
private Channel channel;
private Bootstrap b = null;
private String commonAddress;
private int receiveSeqNum = 0; //接收序号
private int sendSeqNum = 0; // 发送序号,每发送一个后需+1
private boolean isConnected = false;
private boolean isSendTest = false;
private ReentrantLock lock = new ReentrantLock(true);
private ScheduledExecutorService service_test = null;
private ScheduledExecutorService service_connect = null;
private Semaphore semaphore = new Semaphore(1);
private String clientId;
private boolean isClose = false;
ChannelFuture future = null;
public ChannelFutureListener channelFutureListener = new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
if (isClose) {
return;
}
future.addListener(this);
if (future.isSuccess() && future.channel().isActive()) {
isConnected = true;
if (service_connect != null) {
service_connect.shutdownNow();
service_connect = null;
}
Logger.getLogger(this.getClass()).debug("连接服务器成功");
} else {
isConnected = false;
Logger.getLogger(this.getClass()).debug("连接服务器失败, 重新连接");
// future.cause().printStackTrace();
connect2Clinet(clientId);
}
}
};
// 连接服务端的端口号地址和端口号
public IEC104Client(String host, int port) {
this.host = host;
this.port = port;
}
private void connect2Clinet(String serviceId) {
final EventLoopGroup group = new NioEventLoopGroup();
IEC104Client client = this;
if (service_connect != null) {
service_connect.shutdownNow();
service_connect = null;
}
Runnable connect_runnable = new Runnable() {
public void run() {
try {
b = new Bootstrap();
b.group(group).channel(NioSocketChannel.class) // 使用NioSocketChannel来作为连接用的channel类
.handler(new ChannelInitializer<SocketChannel>() { // 绑定连接初始化器
@Override
public void initChannel(SocketChannel ch) throws Exception {
Logger.getLogger(this.getClass()).debug("正在连接中...");
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(new IdleStateHandler(30, 30, 60, TimeUnit.SECONDS));
pipeline.addLast(new IEC104Decoder(serviceId)); // 编码
pipeline.addLast(new IEC104Encoder(serviceId)); // 解码
pipeline.addLast(new IEC104NewHandler(client)); // 业务处理类
}
});
// 发起异步连接请求,绑定连接端口和host信息
future = b.connect(host, port).sync();
future.addListener(channelFutureListener);
channel = future.channel();
channel.closeFuture().sync();
} catch (Exception e) {
Logger.getLogger(this.getClass()).error("connect to " + host + ":" + port + "error: " + e.getMessage());
}
}
};
service_connect = Executors.newSingleThreadScheduledExecutor();
// 第二个参数为首次执行的延时时间,第三个参数为定时执行的间隔时间
service_connect.scheduleAtFixedRate(connect_runnable, 10, 10, TimeUnit.SECONDS);
}
public void closeChannel() {
future.addListener(channelFutureListener);
channel.close();
}
public void init(String serviceId) throws Exception {
connect2Clinet(serviceId);
}
public Channel getChannel() {
return channel;
}
// public void start() {
// if (ObjectUtils.isEmpty(channel)) {
// throw new YeeException("客户端初始化失败");
// }
// }
// public void sendMessage(String strBytes) {
// ChannelPromise promise = this.channel.newPromise();
// this.channel.writeAndFlush(strBytes, promise);
// }
public boolean isConnected() {
return isConnected;
}
// public String sendACKMessage() {
// String recStr = null;
// try {
// if(lock.tryLock(0, TimeUnit.SECONDS)) {
// ChannelPromise promise = this.channel.newPromise();
// if (this.receiveSeqNum >= sendSeqNum + 1) {
// this.receiveSeqNum += 1;
// } else {
// this.receiveSeqNum = sendSeqNum + 1;
// }
//
// byte[] recNum = new byte[2];
// recNum[0] = (byte) (this.receiveSeqNum << 1);
// recNum[1] = (byte) (this.receiveSeqNum >> 7);
// recStr = ChangeUtils.toHexString(recNum);
// this.channel.writeAndFlush("68040100" + recStr, promise);
//
// if (lock.isLocked()) {
// lock.unlock();
// }
// } else {
// sendTestMessage();
// }
// } catch (InterruptedException e) {
// Logger.getLogger(this.getClass()).error(e.getMessage());
// }
// return recStr;
// }
// public boolean sendSOEMessage(String asduBytes) {
// return sendIMessage(asduBytes);
// }
/**
* 启动循环发送测试报文
*/
// public void sendTestMessage() {
// synchronized(this) {
// if (service_test != null) {
// return;
// }
// isSendTest = true;
// Runnable test_runnable = new Runnable() {
// public void run() {
// try {
// ChannelPromise promise = channel.newPromise();
// channel.writeAndFlush("680443000000", promise);
// } catch (Exception e) {
// e.printStackTrace();
// }
// }
// };
// service_test = Executors.newSingleThreadScheduledExecutor();
// // 第二个参数为首次执行的延时时间,第三个参数为定时执行的间隔时间
// service_test.scheduleAtFixedRate(test_runnable, 0, 10, TimeUnit.SECONDS);
// }
// }
/**
* 结束循环发送测试报文
*/
// public void relaseTest() {
// this.isSendTest = false;
// if (service_test != null) {
// service_test.shutdownNow();
// service_test = null;
// semaphore.release();
// }
// }
/**
* 发送I帧报文
* @param asduBytes
* @return
*/
// public boolean sendIMessage(String asduBytes) {
//
// StringBuffer sBuffer = new StringBuffer("68");
// int asduLen = ChangeUtils.hexStringToBytes(asduBytes).length;
// int apduLen = asduLen + 4;
// boolean startSend = true;
// try {
// do {
// if (!startSend) {
// sendTestMessage();
// } else {
// startSend = false;
// }
// } while(!semaphore.tryAcquire(15, TimeUnit.SECONDS));
//
//
//// if (!isSendTest && lock.tryLock(15, TimeUnit.SECONDS)) {
// byte[] recNum = new byte[2];
// recNum[0] = (byte) (this.receiveSeqNum << 1);
// recNum[1] = (byte) (this.receiveSeqNum >> 7);
// String recStr = ChangeUtils.toHexString(recNum);
//
// byte[] sendNum = new byte[2];
// sendNum[0] = (byte) (this.sendSeqNum << 1);
// sendNum[1] = (byte) (this.sendSeqNum >> 7);
// this.sendSeqNum += 1;
// String sendStr = ChangeUtils.toHexString(sendNum);
//
// byte len = (byte) apduLen;
// sBuffer.append(Integer.toHexString(len & 0xFF));
// sBuffer.append(sendStr);
// sBuffer.append(recStr);
// sBuffer.append(asduBytes);
//
// ChannelPromise promise = this.channel.newPromise();
//
// this.channel.writeAndFlush(sBuffer.toString(), promise);
//
// return true;
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// return false;
// }
// public void relase() {
// if (lock.isLocked()) {
// lock.unlock();
// }
// semaphore.release();
// }
// public int getReceiveSeqNum() {
// return receiveSeqNum;
// }
//
// public void setReceiveSeqNum(int receiveSeqNum) {
// this.receiveSeqNum = receiveSeqNum;
// }
//
// public int getSendSeqNum() {
// return sendSeqNum;
// }
//
// public void setSendSeqNum(int sendSeqNum) {
// this.sendSeqNum = sendSeqNum;
// }
//
// public boolean isSendTest() {
// return isSendTest;
// }
public String getCommonAddress() {
return commonAddress;
}
public void setCommonAddress(String commonAddress) {
this.commonAddress = commonAddress;
}
public void close() {
// isClose = true;
// this.channel.close();
// if (lock.isLocked()) {
// lock.unlock();
// }
// relaseTest();
// if (service_connect != null) {
// service_connect.shutdownNow();
// service_connect = null;
// }
}
public String getClientId() {
return clientId;
}
public void setClientId(String clientId) {
this.clientId = clientId;
}
}
package com.yeejoin.amos.iec104.tcp.client;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import com.yeejoin.amos.connect.dao.entity.ConfigVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import com.yeejoin.amos.iec104.business.dao.repository.IServiceConfDao;
@Component
@Scope("singleton")
public class IEC104ClientManager {
private static ConcurrentHashMap<String, IEC104Client> servers = new ConcurrentHashMap<String, IEC104Client>();
public static boolean isDebug = false;
@Autowired
private IServiceConfDao iServiceConfDao;
public void init() {
List<ConfigVo> list = iServiceConfDao.findAllByServiceType("IEC_SERVER");
for (ConfigVo vo : list) {
if (!ObjectUtils.isEmpty(vo.getIp())) {
IEC104Client iec104Client = new IEC104Client(vo.getIp(), Integer.parseInt(vo.getPort()));
iec104Client.setCommonAddress(vo.getCommonAddress());
try {
iec104Client.setClientId(vo.getServiceId());
iec104Client.init(vo.getServiceId());
} catch (Exception e) {
e.printStackTrace();
}
servers.put(vo.getIp()+":" +vo.getPort(), iec104Client);
}
}
}
public void createClient(String ip, String port, String commonAddress) {
if (ObjectUtils.isEmpty(port)) {
port = "2404";
}
if (!ObjectUtils.isEmpty(ip) && !ObjectUtils.isEmpty(port)) {
if (servers.contains(ip+":"+port)) {
return;
}
IEC104Client iec104Client = new IEC104Client(ip, Integer.parseInt(port));
iec104Client.setCommonAddress(commonAddress);
try {
iec104Client.init(commonAddress);
} catch (Exception e) {
e.printStackTrace();
}
servers.put(ip+":"+port, iec104Client);
}
}
public void closeClient(String ip, String port) {
IEC104Client client = servers.get(ip+":"+port);
client.close();
servers.remove(ip+":"+port);
}
public void removeClientByIp(String ip) {
servers.remove(ip);
}
/**
* 根据IP获取同服务器的连接
* @param ip
* @return
*/
public IEC104Client getServerByIp(String ip) {
return servers.get(ip);
}
/**
* 向指定ip的服务端发送数据
* @param ip
* @param strBytes
*/
// public void sendMessageToServer(String ip, String strBytes) {
// IEC104Client server = servers.get(ip);
// if (!ObjectUtils.isEmpty(server) && server.isConnected()) {
// server.sendMessage(strBytes);
// } else {
// throw new YeeException("没有获取到服务");
// }
// }
/**
* 广播发送数据
* @param strBytes
*/
// public void broadcastMessage(String strBytes) {
// for (IEC104Client client : servers.values()) {
// if (client.isConnected()) {
// client.sendMessage(strBytes);
// }
// }
// }
/**
* 获取所有连接的客户端
* @return
*/
public ConcurrentHashMap<String, IEC104Client> getServers() {
return servers;
}
public Collection<IEC104Client> getClients() {
return servers.values();
}
}
package com.yeejoin.amos.iec104.tcp.client;
import java.util.Date;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
import org.apache.log4j.Logger;
import org.springframework.util.ObjectUtils;
import com.yeejoin.amos.iec104.tcp.client.invoke.ApduQueue;
import com.yeejoin.amos.iec104.tcp.entity.Apdu;
import com.yeejoin.amos.iec104.tcp.entity.ServerData;
import com.yeejoin.amos.iec104.tcp.utils.ChangeUtils;
import com.yeejoin.amos.iec104.tcp.utils.Constant;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelPromise;
import io.netty.channel.SimpleChannelInboundHandler;
public class IEC104NewHandler extends SimpleChannelInboundHandler<Apdu>{
public IEC104Client client = null; //接收序号
private ChannelHandlerContext ctx;
int receiveNum = 0;
int sendNum = 0;
private long recordTime;
private ReentrantLock serialLock = new ReentrantLock();
private boolean stopCommunication = false;
private boolean recIpackate = false;
ScheduledExecutorService test_Communication = null;
ScheduledExecutorService eecruiting_Communication = null;
ScheduledExecutorService send_Communication = null;
ScheduledExecutorService ack_Communication = null;
ScheduledExecutorService startService = null;
private BlockingQueue<String> handleBlockingSendQueue = new LinkedBlockingQueue<String>();
public IEC104NewHandler(IEC104Client client) {
this.client = client;
}
@Override
protected void channelRead0(ChannelHandlerContext ctx, Apdu apdu) throws Exception {
try {
Date date = new Date();
this.recordTime = date.getTime();
if (apdu.getApciType() == Apdu.ApciType.I_FORMAT) {
receiveNum = apdu.getSendSeqNumber();
recIpackate = true;
handleData(apdu);
} else if (apdu.getApciType() == Apdu.ApciType.S_FORMAT) {
Logger.getLogger(this.getClass()).warn("返回S确认帧");
if (apdu.getReceiveSeqNumber() != sendNum) {
close();
}
} else if (apdu.getApciType() == Apdu.ApciType.STARTDT_ACT) {
handleBlockingSendQueue.add("68040B000000");
if (test_Communication == null) {
test_Communication = Executors.newSingleThreadScheduledExecutor();
test_Communication.scheduleAtFixedRate(test_runnable, Constant.Z_Z_INITIALDELAY, 1, TimeUnit.SECONDS);
}
} else if (apdu.getApciType() == Apdu.ApciType.STOPDT_ACT) {
handleBlockingSendQueue.add("680423000000");
close();
} else if (apdu.getApciType() == Apdu.ApciType.TESTFR_ACT) {
handleBlockingSendQueue.add("680483000000");
Logger.getLogger(this.getClass()).debug("确认测试消息,U类型");
} else if (apdu.getApciType() == Apdu.ApciType.STARTDT_CON) {
Logger.getLogger(this.getClass()).debug("启动确认帧回复,U类型");
if (startService != null) {
startService.shutdownNow();
startService = null;
}
// 添加测试报文
if (test_Communication == null) {
test_Communication = Executors.newSingleThreadScheduledExecutor();
test_Communication.scheduleAtFixedRate(test_runnable, Constant.Z_Z_INITIALDELAY, 1, TimeUnit.SECONDS);
}
if (ack_Communication == null) {
addACKDatalistener();
}
} else if (apdu.getApciType() == Apdu.ApciType.TESTFR_CON) {
Logger.getLogger(this.getClass()).debug("确认测试消息回复,U类型");
if (eecruiting_Communication == null) {
eecruiting_Communication = Executors.newSingleThreadScheduledExecutor();
eecruiting_Communication.scheduleAtFixedRate(Recruiting_runnable, Constant.Z_Z_INITIALDELAY, Constant.Z_Z_PREIOD, TimeUnit.SECONDS);
}
} else {
Logger.getLogger(this.getClass()).debug("其它报文:" + apdu.getApciType());
}
} catch (Exception e){
e.printStackTrace();
Logger.getLogger(this.getClass()).debug("异常错误,"+ e);
}
}
private void handleData(Apdu apdu) {
if (apdu.getAsdu().getTypeId()== 100) {
return;
}
ServerData serverData = new ServerData();
serverData.setApdu(apdu);
serverData.setServerId(client.getClientId());
ApduQueue.getInstance().add(serverData);
}
private void addACKDatalistener() {
recordTime = new Date().getTime();
ack_Communication = Executors.newSingleThreadScheduledExecutor();
// 第二个参数为首次执行的延时时间,第三个参数为定时执行的间隔时间
ack_Communication.scheduleAtFixedRate(ack_runnable, 1, 1, TimeUnit.SECONDS);
}
Runnable ack_runnable = new Runnable() {
@Override
public void run() {
long currentTime = new Date().getTime();
if (recIpackate && ((currentTime - recordTime) / 1000) > 5) {
recIpackate = false;
byte[] recNum = new byte[2];
receiveNum ++;
recNum[0] = (byte) (receiveNum << 1);
recNum[1] = (byte) (receiveNum >> 7);
String recStr = ChangeUtils.toHexString(recNum);
handleBlockingSendQueue.add("68040100" + recStr);
}
}
};
Runnable test_runnable = new Runnable() {
@Override
public void run() {
Date date = new Date();
if (!stopCommunication && ((date.getTime() - recordTime) / 1000) >= 10) {
recordTime = date.getTime();
handleBlockingSendQueue.add("680443000000");
}
}
};
Runnable Recruiting_runnable = new Runnable() {
public void run() {
try {
boolean isSend = false;
do {
byte[] sendNumBytes = new byte[2];
byte[] recNumBytes = new byte[2];
serialLock.lock();
recIpackate = false;
sendNumBytes[0] = (byte) (sendNum << 1);
sendNumBytes[1] = (byte) (sendNum >> 7);
recNumBytes[0] = (byte) (receiveNum << 1);
recNumBytes[1] = (byte) (receiveNum >> 7);
String recStr = ChangeUtils.toHexString(recNumBytes);
String sendStr = ChangeUtils.toHexString(sendNumBytes);
sendNum ++;
serialLock.unlock();
String commonAddress = client.getCommonAddress();
String zzPackate = "680E"+sendStr+recStr+"64010600"+commonAddress+"00000014";
handleBlockingSendQueue.add(zzPackate.replace(" ", "").toUpperCase());
isSend = true;
} while(!isSend);
} catch (Exception e) {
e.printStackTrace();
}
}
};
private void addSendDatalistener() {
send_Communication = Executors.newSingleThreadScheduledExecutor();
// 第二个参数为首次执行的延时时间,第三个参数为定时执行的间隔时间
send_Communication.execute(send_runnable);;
}
Runnable send_runnable = new Runnable() {
@Override
public void run() {
while(!stopCommunication) {
try {
String data = handleBlockingSendQueue.take();
ctx.channel().writeAndFlush(data.replace(" ", ""), ctx.channel().newPromise());
recIpackate = false;
} catch (Exception e) {
e.printStackTrace();
}
}
}
};
Runnable runnable = new Runnable() {
public void run() {
handleBlockingSendQueue.add("680407000000");
}
};
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
super.channelActive(ctx);
this.ctx = ctx;
addSendDatalistener();
startService = Executors.newSingleThreadScheduledExecutor();
// 第二个参数为首次执行的延时时间,第三个参数为定时执行的间隔时间
startService.scheduleAtFixedRate(runnable, Constant.Z_Z_INITIALDELAY, Constant.S_S_PREIOD, TimeUnit.SECONDS);
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
super.channelInactive(ctx);
this.ctx = null;
close();
}
private void close() {
receiveNum = 0;
sendNum = 0;
stopCommunication = true;
if (startService != null) {
startService.shutdownNow();
startService = null;
}
if (send_Communication != null) {
send_Communication.shutdownNow();
send_Communication = null;
}
if (test_Communication != null) {
test_Communication.shutdownNow();
test_Communication = null;
}
if (ack_Communication != null) {
ack_Communication.shutdownNow();
ack_Communication = null;
}
if (eecruiting_Communication != null) {
eecruiting_Communication.shutdownNow();
eecruiting_Communication = null;
}
handleBlockingSendQueue.clear();
this.client.closeChannel();
}
}
package com.yeejoin.amos.iec104.tcp.client;
import java.util.Properties;
import java.util.concurrent.ScheduledExecutorService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.yeejoin.amos.iec104.tcp.utils.FileUtils;
import net.sf.json.JSONArray;
public class Init {
private static Log log = LogFactory.getLog(Init.class);
public static Properties typeIdProp = null;
public static Properties causeProp = null;
public static Properties debugProp = null;
public static JSONArray points = null;
public static JSONArray soePoints = null;
public static int consecutiveTransNum = 5;
public static int zzTransNum = 10;
public static int soeTransNum = 1;
public static int secTransNum = 1;
public static int infomationStartAddress = 1;
public static void start(){
initBusinessData();
}
public static void initBusinessData(){
try {
log.debug("解析配置文件");
typeIdProp = FileUtils.loadPropFile("typeId.properties");
causeProp = FileUtils.loadPropFile("cause.properties");
} catch (Exception e) {
e.printStackTrace();
}
}
}
package com.yeejoin.amos.iec104.tcp.client.invoke;
import java.util.Date;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ScheduledExecutorService;
import org.apache.log4j.Logger;
import org.springframework.beans.BeanUtils;
import com.yeejoin.amos.iec104.business.entity.mybatis.RecData;
import com.yeejoin.amos.iec104.tcp.entity.Apdu;
import com.yeejoin.amos.iec104.tcp.entity.Asdu;
import com.yeejoin.amos.iec104.tcp.entity.IeCP56Time2a;
import com.yeejoin.amos.iec104.tcp.entity.IeQuality;
import com.yeejoin.amos.iec104.tcp.entity.IeShortFloat;
import com.yeejoin.amos.iec104.tcp.entity.IeSinglePointWithQuality;
import com.yeejoin.amos.iec104.tcp.entity.InformationElement;
import com.yeejoin.amos.iec104.tcp.entity.InformationObject;
import com.yeejoin.amos.iec104.tcp.entity.ServerData;
public class ApduQueue {
private static final BlockingQueue<ServerData> blockingQueue = new LinkedBlockingQueue<ServerData>();
ScheduledExecutorService service_apdu = null;
private volatile static ApduQueue instance = null;
private ApduQueue() {}
public static ApduQueue getInstance(){
//先检查实例是否存在,如果不存在才进入下面的同步块
if(instance == null){
//同步块,线程安全的创建实例
synchronized(ApduQueue.class){
//再次检查实例是否存在,如果不存在才真的创建实例
if(instance == null){
instance = new ApduQueue();
}
}
}
return instance;
}
/**
* 启动apdu数据消费任务
*/
public void start() {
service_apdu = Executors.newSingleThreadScheduledExecutor();
// 第二个参数为首次执行的延时时间,第三个参数为定时执行的间隔时间
service_apdu.execute(task_runnable);
}
public void add(ServerData apdu) {
blockingQueue.add(apdu);
}
Runnable task_runnable = new Runnable() {
public void run() {
while(true) {
try {
ServerData serverData = blockingQueue.take();
String serverId = serverData.getServerId();
Apdu apdu = serverData.getApdu();
if (apdu.getApciType() == Apdu.ApciType.I_FORMAT) {
Asdu asdu = apdu.getAsdu();
int numberOfSequenceElements = 0;
switch (asdu.getTypeId()) {
// 1 单点遥信
case 1:
InformationObject[] informationObjects = asdu.getInformationObjects();
for (InformationObject obj : informationObjects) {
InformationElement[][] informationElement = obj.getInformationElements();
int informationObjectAddress = obj.getInformationObjectAddress();
numberOfSequenceElements = asdu.getSequenceLength();
asdu.isSequenceOfElements();
for (int i = 0; i < numberOfSequenceElements; i++) {
RecData data = new RecData(serverId);
data.setCommonAddress(asdu.getCommonAddress());
data.setCreatedTime(new Date());
data.setDataType(1);
data.setInformationAddress(informationObjectAddress);
IeSinglePointWithQuality singlePoint = (IeSinglePointWithQuality) informationElement[i][0];
data.setIsBlocked(singlePoint.isBlocked() ? 0 : 1);
data.setIsSubstituted(singlePoint.isSubstituted() ? 0 : 1);
data.setIsNotTopical(singlePoint.isNotTopical() ? 0 : 1);
data.setIsInvalid(singlePoint.isInvalid() ? 0 : 1);
data.setValue(singlePoint.isOn() + "");
informationObjectAddress++;
data.setQuality(singlePoint.toJson().toString());
RecDataQueue.getInstance().add(data);
}
}
break;
// 13 浮点型遥测
case 13:
InformationObject[] floatInformationObjects = asdu.getInformationObjects();
numberOfSequenceElements = asdu.getSequenceLength();
for (int i = 0; i < numberOfSequenceElements; i++) {
InformationObject obj = floatInformationObjects[i];
InformationElement[][] informationElement = obj.getInformationElements();
int informationObjectAddress = obj.getInformationObjectAddress();
// for (int i = 0; i < numberOfSequenceElements; i++) {
RecData data = new RecData(serverId);
data.setCommonAddress(asdu.getCommonAddress());
data.setCreatedTime(new Date());
data.setDataType(2);
data.setInformationAddress(informationObjectAddress);
IeShortFloat shortFloat = (IeShortFloat) informationElement[0][0];
IeQuality ieQuality = (IeQuality) informationElement[0][1];
data.setValue(shortFloat.getValue() + "");
data.setQuality(ieQuality.toJson().toString());
data.setIsBlocked(ieQuality.isBlocked() ? 0 : 1);
data.setIsSubstituted(ieQuality.isSubstituted() ? 0 : 1);
data.setIsNotTopical(ieQuality.isNotTopical() ? 0 : 1);
data.setIsInvalid(ieQuality.isInvalid() ? 0 : 1);
data.setIsOverflow(ieQuality.isOverflow() ? 0: 1);
informationObjectAddress++;
RecDataQueue.getInstance().add(data);
// }
}
break;
// 30 带 CP56Time2a 时标的单点信息
case 30:
InformationObject[] informationCP56Time2aObjects = asdu.getInformationObjects();
// for (InformationObject obj : informationCP56Time2aObjects) {
numberOfSequenceElements = asdu.getSequenceLength();
for (int i = 0; i < numberOfSequenceElements; i++) {
InformationObject obj = informationCP56Time2aObjects[i];
InformationElement[][] informationElement = obj.getInformationElements();
int informationObjectAddress = obj.getInformationObjectAddress();
// asdu.isSequenceOfElements();
RecData data = new RecData(serverId);
data.setCommonAddress(asdu.getCommonAddress());
data.setCreatedTime(new Date());
data.setDataType(1);
data.setInformationAddress(informationObjectAddress);
IeSinglePointWithQuality singlePoint = (IeSinglePointWithQuality) informationElement[0][0];
IeCP56Time2a ieCP56Time2a = (IeCP56Time2a) informationElement[0][1];
data.setValue(singlePoint.isOn() + "");
data.setOccurTime(ieCP56Time2a.getDate());
data.setSoe(1);
data.setQuality(singlePoint.toJson().toString());
data.setIsBlocked(singlePoint.isBlocked() ? 0 : 1);
data.setIsSubstituted(singlePoint.isSubstituted() ? 0 : 1);
data.setIsNotTopical(singlePoint.isNotTopical() ? 0 : 1);
data.setIsInvalid(singlePoint.isInvalid() ? 0 : 1);
Logger.getLogger(this.getClass()).debug("31类型 I帧: " +data.toString());
RecDataQueue.getInstance().add(data);
// }
}
break;
// 31 带 CP56Time2a 时标的双点信息
case 31:
InformationObject[] twoInformationCP56Time2aObjects = asdu.getInformationObjects();
numberOfSequenceElements = asdu.getSequenceLength();
//for (InformationObject obj : twoInformationCP56Time2aObjects) {
for (int i = 0; i < numberOfSequenceElements; i++) {
InformationObject obj = twoInformationCP56Time2aObjects[i];
InformationElement[][] informationElement = obj.getInformationElements();
int informationObjectAddress = obj.getInformationObjectAddress();
asdu.isSequenceOfElements();
RecData data = new RecData(serverId);
data.setCommonAddress(asdu.getCommonAddress());
data.setCreatedTime(new Date());
data.setDataType(1);
data.setInformationAddress(informationObjectAddress);
IeSinglePointWithQuality singlePoint = (IeSinglePointWithQuality) informationElement[0][0];
IeCP56Time2a ieCP56Time2a = (IeCP56Time2a) informationElement[0][2];
data.setValue(singlePoint.isOn() + "");
data.setOccurTime(ieCP56Time2a.getDate());
data.setQuality(singlePoint.toJson().toString());
data.setIsBlocked(singlePoint.isBlocked() ? 0 : 1);
data.setIsSubstituted(singlePoint.isSubstituted() ? 0 : 1);
data.setIsNotTopical(singlePoint.isNotTopical() ? 0 : 1);
data.setIsInvalid(singlePoint.isInvalid() ? 0 : 1);
data.setSoe(1);
RecDataQueue.getInstance().add(data);
informationObjectAddress++;
RecData data1 = new RecData();
BeanUtils.copyProperties(data, data1);
data1.setInformationAddress(informationObjectAddress);
IeSinglePointWithQuality singlePoint1 = (IeSinglePointWithQuality) informationElement[0][1];
data1.setQuality(singlePoint1.toJson().toString());
RecDataQueue.getInstance().add(data1);
//}
}
break;
default:
Logger.getLogger(this.getClass()).error("其他类型 I帧: " + asdu.getTypeId());
}
}
} catch (Exception e) {
e.printStackTrace();
Logger.getLogger(this.getClass()).error(e.getMessage());
}
}
}
};
}
package com.yeejoin.amos.iec104.tcp.client.invoke;
import java.util.LinkedList;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import com.yeejoin.amos.connect.dao.entity.PointConfigVo;
import org.apache.log4j.Logger;
import org.springframework.util.ObjectUtils;
import com.yeejoin.amos.iec104.business.constants.IEC104Constant;
import com.yeejoin.amos.iec104.business.param.AlarmParam;
import com.yeejoin.amos.iec104.business.service.intfc.IClientListenService;
import com.yeejoin.amos.iec104.business.service.intfc.IConfService;
import com.yeejoin.amos.iec104.business.service.intfc.IPointConfigService;
import com.yeejoin.amos.iec104.context.FireAutoIntfContext;
public class GeneralDataQueue {
private static final BlockingQueue<AlarmParam> blockingQueue = new LinkedBlockingQueue<AlarmParam>();
ScheduledExecutorService service_general = null;
IClientListenService clientListenService;
IPointConfigService pointConfigService;
IConfService confService;
private volatile static GeneralDataQueue instance = null;
private GeneralDataQueue() {
clientListenService = (IClientListenService) FireAutoIntfContext.getInstance().getBean(IClientListenService.class);
confService = (IConfService) FireAutoIntfContext.getInstance().getBean(IConfService.class);
pointConfigService = (IPointConfigService) FireAutoIntfContext.getInstance().getBean(IPointConfigService.class);
}
public static GeneralDataQueue getInstance(){
//先检查实例是否存在,如果不存在才进入下面的同步块
if(instance == null){
//同步块,线程安全的创建实例
synchronized(GeneralDataQueue.class){
//再次检查实例是否存在,如果不存在才真的创建实例
if(instance == null){
instance = new GeneralDataQueue();
}
}
}
return instance;
}
/**
* 启动apdu数据消费任务
*/
public void start() {
service_general = Executors.newSingleThreadScheduledExecutor();
// 第二个参数为首次执行的延时时间,第三个参数为定时执行的间隔时间
service_general.scheduleAtFixedRate(task_runnable, 5, 10, TimeUnit.SECONDS);
}
public void add(AlarmParam recData) {
blockingQueue.add(recData);
}
Runnable task_runnable = new Runnable() {
public void run() {
while(true) {
try {
AlarmParam param1 = blockingQueue.take();
LinkedList<AlarmParam> datas = new LinkedList<AlarmParam>();
PointConfigVo vo = pointConfigService.findByServicesIdAndInfoAddress(param1.getServiceId(), Integer.valueOf(param1.getInformationAddress()));
param1.setPointCode(vo.getPointCode());
datas.add(param1);
boolean isEmpty = false;
do {
AlarmParam param = blockingQueue.poll(1, TimeUnit.SECONDS);
if (!ObjectUtils.isEmpty(param)) {
PointConfigVo vo1 = pointConfigService.findByServicesIdAndInfoAddress(param.getServiceId(), Integer.valueOf(param.getInformationAddress()));
if (!ObjectUtils.isEmpty(vo1)) {
param.setPointCode(vo1.getPointCode());
datas.add(param);
if (datas.size() > 10000) {
clientListenService.sendDatas(IEC104Constant.GENERAL_MESSAGE, datas);
datas.clear();
}
} else {
Logger.getLogger(this.getClass()).error(param.getServiceId() + " have not " + param.getInformationAddress());
}
} else {
isEmpty = true;
}
} while(!isEmpty);
try {
if (!ObjectUtils.isEmpty(datas)) {
clientListenService.sendDatas(IEC104Constant.GENERAL_MESSAGE, datas);
}
datas.clear();
} catch (Exception e) {
}
} catch (Exception e) {
Logger.getLogger(this.getClass()).error(e.getMessage());
e.printStackTrace();
}
}
}
};
}
package com.yeejoin.amos.iec104.tcp.client.invoke;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ScheduledExecutorService;
import com.yeejoin.amos.connect.dao.entity.PointConfigVo;
import org.apache.log4j.Logger;
import com.yeejoin.amos.iec104.business.constants.IEC104Constant;
import com.yeejoin.amos.iec104.business.entity.mybatis.RecData;
import com.yeejoin.amos.iec104.business.param.AlarmParam;
import com.yeejoin.amos.iec104.business.service.intfc.IClientListenService;
import com.yeejoin.amos.iec104.business.service.intfc.IConfService;
import com.yeejoin.amos.iec104.business.service.intfc.IPointConfigService;
import com.yeejoin.amos.iec104.context.FireAutoIntfContext;
public class RecDataQueue {
private static final BlockingQueue<RecData> blockingQueue = new LinkedBlockingQueue<RecData>();
private static final BlockingQueue<RecData> soeBlockingQueue = new LinkedBlockingQueue<RecData>();
ScheduledExecutorService service_apdu = null;
ScheduledExecutorService service_soe = null;
IClientListenService clientListenService;
IConfService confService;
IPointConfigService pointConfigService;
private volatile static RecDataQueue instance = null;
private RecDataQueue() {
clientListenService = (IClientListenService) FireAutoIntfContext.getInstance().getBean(IClientListenService.class);
confService = (IConfService) FireAutoIntfContext.getInstance().getBean(IConfService.class);
pointConfigService = (IPointConfigService) FireAutoIntfContext.getInstance().getBean(IPointConfigService.class);
}
public static RecDataQueue getInstance(){
//先检查实例是否存在,如果不存在才进入下面的同步块
if(instance == null){
//同步块,线程安全的创建实例
synchronized(RecDataQueue.class){
//再次检查实例是否存在,如果不存在才真的创建实例
if(instance == null){
instance = new RecDataQueue();
}
}
}
return instance;
}
/**
* 启动apdu数据消费任务
*/
public void start() {
service_apdu = Executors.newSingleThreadScheduledExecutor();
// 第二个参数为首次执行的延时时间,第三个参数为定时执行的间隔时间
service_apdu.execute(task_runnable);
service_soe = Executors.newSingleThreadScheduledExecutor();
service_soe.execute(soe_runnable);
}
public void add(RecData recData) {
blockingQueue.add(recData);
}
Runnable task_runnable = new Runnable() {
public void run() {
while(true) {
try {
RecData data = blockingQueue.take();
if (data.getSoe() == 1) {
Logger.getLogger(this.getClass()).debug("----> soe is event pointCode is " + data.getPointCode() );
soeBlockingQueue.add(data);
// sendAlarm(data);
} else {
AlarmParam alarm = new AlarmParam();
alarm.setInformationAddress(data.getInformationAddress()+"");
alarm.setState(data.getValue());
alarm.setServiceId(data.getServerId());
alarm.setIsInvalid(data.getIsInvalid());
alarm.setPointCode(data.getPointCode());
alarm.setSoe(data.getSoe());
GeneralDataQueue.getInstance().add(alarm);
}
} catch (Exception e) {
Logger.getLogger(this.getClass()).error(e.getMessage());
e.printStackTrace();
}
}
}
};
Runnable soe_runnable = new Runnable() {
public void run() {
while(true) {
try {
RecData data = soeBlockingQueue.take();
sendAlarm(data);
} catch (Exception e) {
Logger.getLogger(this.getClass()).error(e.getMessage());
e.printStackTrace();
}
}
}
};
public void sendAlarm(RecData data) {
AlarmParam alarm = new AlarmParam();
alarm.setInformationAddress(data.getInformationAddress()+"");
alarm.setState(data.getValue());
alarm.setServiceId(data.getServerId());
alarm.setIsInvalid(data.getIsInvalid());
PointConfigVo vo = pointConfigService.findByServicesIdAndInfoAddress(data.getServerId(), data.getInformationAddress());
alarm.setPointCode(vo.getPointCode());
alarm.setSoe(data.getSoe());
try {
// ConfigVo vo = confService.getServerByTypeAndServiceId("IEC_SERVER", data.getServerId());
clientListenService.sendData(IEC104Constant.ALARM_MESSAGE, vo.getChannelNo(), alarm);
} catch (Exception e) {
e.printStackTrace();
}
}
}
package com.yeejoin.amos.iec104.tcp.entity;
import java.io.IOException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import io.netty.buffer.ByteBuf;
public class Apdu {
private Log log = LogFactory.getLog(Apdu.class);
private int sendSeqNum = 0;
private int receiveSeqNum = 0;
private ApciType apciType;
private Asdu asdu = null;
//枚举,APCI类型,即I帧,S帧,U帧
public enum ApciType {
I_FORMAT, //I帧
S_FORMAT, //S帧
TESTFR_CON, //U帧,测试确认
TESTFR_ACT, //U帧,测试命令
STOPDT_CON, //U帧,停止确认
STOPDT_ACT, //U帧,停止命令
STARTDT_CON, //U帧,启动确认
STARTDT_ACT //U帧,启动命令
}
public Apdu(){}
public Apdu(int sendSeqNum, int receiveSeqNum, ApciType apciType, Asdu asdu) {
this.sendSeqNum = sendSeqNum;
this.receiveSeqNum = receiveSeqNum;
this.apciType = apciType;
this.asdu = asdu;
}
public Apdu(ByteBuf dis) throws Exception {
int start = dis.readByte() & 0xff;
int len = dis.readByte() & 0xff;
log.debug("启动帧:" + Integer.toHexString(start));
log.debug("APDU长度:" + len);
byte[] controlFields = new byte[4];
if(start != 104 ){
log.error(new IllegalArgumentException("启动帧错误"));
}else if(len < 4 || len >253){
log.error(new IllegalArgumentException("帧长度有误"));
}else{
//读4字节控制域
dis.readBytes(controlFields);
if((controlFields[0] & 0x01)==0){
//I帧
this.apciType = ApciType.I_FORMAT;
//发送序列号
sendSeqNum = ((controlFields[0] & 0xfe) >> 1) + ((controlFields[1] & 0xff) << 7);
//接收序列号
receiveSeqNum = ((controlFields[2] & 0xfe) >> 1) + ((controlFields[3] & 0xff) << 7);
log.debug("I帧,发送序列号:"+sendSeqNum+",接收序列号:"+receiveSeqNum);
}else if ((controlFields[0] & 0x03)==1){
//S帧
this.apciType = ApciType.S_FORMAT;
receiveSeqNum = ((controlFields[2] & 0xfe) >> 1) + ((controlFields[3] & 0xff) << 7);
log.debug("S帧,接收序列号:"+receiveSeqNum);
}else if ((controlFields[0] & 0x03) == 3){
//U帧
if (controlFields[0] == 0x07){
this.apciType = ApciType.STARTDT_ACT;
log.debug("U帧,启动命令");
}else if (controlFields[0] == 0x0B){
this.apciType = ApciType.STARTDT_CON;
log.debug("U帧启动确认");
}else if (controlFields[0] == 0x13){
this.apciType = ApciType.STOPDT_ACT;
log.debug("U帧停止命令");
}else if (controlFields[0] == 0x23){
this.apciType = ApciType.STOPDT_CON;
log.debug("U帧停止确认");
}else if (controlFields[0] == 0x43){
this.apciType = ApciType.TESTFR_ACT;
log.debug("U帧测试命令");
}else if (controlFields[0] == (byte) 0x83){
this.apciType = ApciType.TESTFR_CON;
log.debug("U帧测试确认");
}
}
}
//构建信息体
if (len > 6) {
this.asdu = new Asdu(dis);
}
}
public int encode(byte[] buffer) throws IOException {
buffer[0] = 0x68;
int length = 4;
if (apciType == ApciType.I_FORMAT) {
buffer[2] = (byte) (sendSeqNum << 1);
buffer[3] = (byte) (sendSeqNum >> 7);
buffer[4] = (byte) (receiveSeqNum << 1);
buffer[5] = (byte) (receiveSeqNum >> 7);
length += asdu.encode(buffer, 6);
}
else if (apciType == ApciType.STARTDT_ACT) {
buffer[2] = 0x07;
buffer[3] = 0x00;
buffer[4] = 0x00;
buffer[5] = 0x00;
}
else if (apciType == ApciType.STARTDT_CON) {
buffer[2] = 0x0b;
buffer[3] = 0x00;
buffer[4] = 0x00;
buffer[5] = 0x00;
}
else if (apciType == ApciType.S_FORMAT) {
buffer[2] = 0x01;
buffer[3] = 0x00;
buffer[4] = (byte) (receiveSeqNum << 1);
buffer[5] = (byte) (receiveSeqNum >> 7);
}
buffer[1] = (byte) length;
return length + 2;
}
public ApciType getApciType(){
return apciType;
}
public int getSendSeqNumber() {
return sendSeqNum;
}
public int getReceiveSeqNumber() {
return receiveSeqNum;
}
public Asdu getAsdu() {
return asdu;
}
}
package com.yeejoin.amos.iec104.tcp.entity;
import java.io.IOException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.yeejoin.amos.iec104.tcp.client.Init;
import com.yeejoin.amos.iec104.tcp.utils.ChangeUtils;
import io.netty.buffer.ByteBuf;
public class Asdu {
private Log log = LogFactory.getLog(Apdu.class);
private final int typeId;
private final boolean isSequenceOfElements;
private int vsq;
private final int addressNum;
private final int causeOfTransmission;
private boolean test;
private boolean negativeConfirm;
private int originatorAddress;
private final int commonAddress;
private InformationObject[] informationObjects;
private byte[] privateInformation;
public Asdu(int typeId, boolean isSequenceOfElements, int causeOfTransmission, boolean test,
boolean negativeConfirm, int originatorAddress, int commonAddress, InformationObject[] informationObjects) {
this.typeId = typeId;
this.isSequenceOfElements = isSequenceOfElements;
this.causeOfTransmission = causeOfTransmission;
this.test = test;
this.negativeConfirm = negativeConfirm;
this.commonAddress = commonAddress;
this.originatorAddress = originatorAddress;
this.informationObjects = informationObjects;
this.privateInformation = null;
if (isSequenceOfElements) {
this.addressNum = informationObjects[0].getInformationElements().length;
} else {
this.addressNum = informationObjects.length;
}
}
public Asdu(ByteBuf in) throws Exception{
//获取类型表示配置文件
this.typeId = in.readByte() & 0xff;
if (Init.typeIdProp.getProperty(String.valueOf(typeId))== null || "".equals(Init.typeIdProp.getProperty(String.valueOf(typeId)))){
log.error(new IOException("无效的类型标识:"+typeId));
}else{
log.debug("类型标识:" + Init.typeIdProp.getProperty(String.valueOf(typeId)));
}
int vsqNum = in.readByte() & 0xff;
String vsqFormat = String.format("%08d",Integer.parseInt(Integer.toBinaryString(vsqNum)));
//可变结构限定词,转为二进制后获取第8位
vsq = Integer.parseInt(vsqFormat.substring(0,1));
//可变结构限定词,获取第1-7位,代表信息数据数目
addressNum = Integer.parseInt(vsqFormat.substring(1,8),2);
if (vsq == 1) {
isSequenceOfElements = true;
log.debug("信息体地址连续:" +isSequenceOfElements+",信息数据条数:" + addressNum);
} else {
isSequenceOfElements = false;
log.debug("信息体地址连续:" +isSequenceOfElements+",信息数据条数:" + addressNum);
}
int numberOfSequenceElements;
int numberOfInformationObjects;
// 根据是否连续来确定信息对象数目、信息元素数目
if (isSequenceOfElements) {
numberOfSequenceElements = addressNum;
numberOfInformationObjects = 1;
}else {
numberOfInformationObjects = addressNum;
numberOfSequenceElements = 1;
}
byte[] cot = new byte[2];
in.readBytes(cot);
//传送原因
causeOfTransmission = Integer.parseInt(ChangeUtils.byteAppend(cot),10);
log.debug("传送原因:" + Init.causeProp.getProperty(String.valueOf(causeOfTransmission)));
//公共地址
byte[] commAddress = new byte[2];
in.readBytes(commAddress);
commonAddress = Integer.parseInt(ChangeUtils.byteAppend(commAddress));
log.debug("公共地址:" + commonAddress);
//信息体
if (typeId < 128) {
informationObjects = new InformationObject[numberOfInformationObjects];
for (int i = 0; i < numberOfInformationObjects; i++) {
informationObjects[i] = new InformationObject(in, typeId, numberOfSequenceElements);
}
privateInformation = null;
}else{
log.debug("");
}
}
public int getTypeId() {
return typeId;
}
public boolean isSequenceOfElements() {
return isSequenceOfElements;
}
public int getSequenceLength() {
return addressNum;
}
public int getCauseOfTransmission() {
return causeOfTransmission;
}
public boolean isTestFrame() {
return test;
}
public boolean isNegativeConfirm() {
return negativeConfirm;
}
public Integer getOriginatorAddress() {
return originatorAddress;
}
public int getCommonAddress() {
return commonAddress;
}
public InformationObject[] getInformationObjects() {
return informationObjects;
}
public byte[] getPrivateInformation() {
return privateInformation;
}
int encode(byte[] buffer, int i) {
int origi = i;
buffer[i++] = (byte) typeId;
if (isSequenceOfElements) {
buffer[i++] = (byte) (addressNum | 0x80);
}else {
buffer[i++] = (byte) addressNum;
}
if (test) {
if (negativeConfirm) {
buffer[i++] = (byte) (causeOfTransmission | 0xC0);
}else {
buffer[i++] = (byte) (causeOfTransmission | 0x80);
}
}else {
if (negativeConfirm) {
buffer[i++] = (byte) (causeOfTransmission | 0x40);
}else {
buffer[i++] = (byte) causeOfTransmission;
}
}
buffer[i++] = (byte) originatorAddress;
buffer[i++] = (byte) commonAddress;
buffer[i++] = (byte) (commonAddress >> 8);
if (informationObjects != null) {
for (InformationObject informationObject : informationObjects) {
i += informationObject.encode(buffer, i);
}
}else {
System.arraycopy(privateInformation, 0, buffer, i, privateInformation.length);
i += privateInformation.length;
}
return i - origi;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
if (informationObjects != null) {
for (InformationObject informationObject : informationObjects) {
builder.append(informationObject.toString());
builder.append("\n");
}
}else {
builder.append("\nPrivate Information:\n");
int l = 1;
for (byte b : privateInformation) {
if ((l != 1) && ((l - 1) % 8 == 0)) {
builder.append(' ');
}
if ((l != 1) && ((l - 1) % 16 == 0)) {
builder.append('\n');
}
l++;
builder.append("0x");
String hexString = Integer.toHexString(b & 0xff);
if (hexString.length() == 1) {
builder.append(0);
}
builder.append(hexString + " ");
}
}
return builder.toString();
}
}
package com.yeejoin.amos.iec104.tcp.entity;
import java.io.IOException;
import io.netty.buffer.ByteBuf;
import net.sf.json.JSONObject;
/**
* 品质描述
*/
abstract class IeAbstractQuality extends InformationElement {
protected int value;
public IeAbstractQuality(boolean blocked, boolean substituted, boolean notTopical, boolean invalid) {
value = 0;
if (blocked) {
value |= 0x10;
}
if (substituted) {
value |= 0x20;
}
if (notTopical) {
value |= 0x40;
}
if (invalid) {
value |= 0x80;
}
}
public IeAbstractQuality(ByteBuf is) throws IOException {
value = (is.readByte() & 0xff);
}
@Override
public int encode(byte[] buffer, int i) {
buffer[i] = (byte) value;
return 1;
}
public boolean isBlocked() {
return (value & 0x10) == 0x10;
}
public boolean isSubstituted() {
return (value & 0x20) == 0x20;
}
public boolean isNotTopical() {
return (value & 0x40) == 0x40;
}
public boolean isInvalid() {
return (value & 0x80) == 0x80;
}
@Override
public String toString() {
return "被封锁: " + isBlocked() + ", 被取代: " + isSubstituted() + ", 非当前值: " + isNotTopical()
+ ", 是否有效: " + isInvalid();
}
public JSONObject toJson() {
JSONObject json = new JSONObject();
json.put("isBlocked", isBlocked());
json.put("isSubstituted", isSubstituted());
json.put("isNotTopical", isNotTopical());
json.put("isInvalid", isInvalid());
return json;
}
}
package com.yeejoin.amos.iec104.tcp.entity;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import org.apache.coyote.http2.ByteUtil;
import io.netty.buffer.ByteBuf;
public class IeCP56Time2a extends InformationElement{
protected byte[] date = new byte[7];
// test
// protected byte[] date = { (byte) 0xAD, (byte)0x39 , (byte)0x1C, (byte)0x10, (byte)0x7A , (byte)0x0B, (byte)0x05};
public IeCP56Time2a(ByteBuf is) throws IOException {
if (is.readableBytes() > 7) {
is.readBytes(date);
}
}
public IeCP56Time2a() {
}
@Override
public int encode(byte[] buffer, int i) {
return 1;
}
public Date getDate() {
int handleS = ByteUtil.getTwoBytes(date, 0);
int second = handleS / 1000;
int milliSecond = handleS % 1000;
int minute = ByteUtil.getOneByte(date, 2);
int hour = ByteUtil.getOneByte(date, 3);
int day = ByteUtil.getOneByte(date, 4);
int month = ByteUtil.getOneByte(date, 5);
int year = ByteUtil.getOneByte(date, 6);
String yearStr = Integer.toHexString(year);
yearStr = yearStr.length() > 1?yearStr:"0".concat(yearStr);
Calendar calendar = new GregorianCalendar();
year = Integer.parseInt(String.valueOf(calendar.get(Calendar.YEAR)).substring(0, 2) + yearStr);
Calendar cal = Calendar.getInstance();
cal.set(Calendar.YEAR, year);
cal.set(Calendar.MONTH, month);
cal.set(Calendar.DATE, day);
cal.set(Calendar.HOUR_OF_DAY, hour);
cal.set(Calendar.MINUTE, minute);
cal.set(Calendar.SECOND, second);
cal.set(Calendar.MILLISECOND, milliSecond);
return cal.getTime();
}
public String getFormatDate(String pattern) {
Date d = getDate();
SimpleDateFormat sdf = new SimpleDateFormat(pattern);
return sdf.format(d);
}
// public static void main(String[] args) {
// IeCP56Time2a a = new IeCP56Time2a();
// Date d = a.getDate();
// SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// System.out.println(sdf.format(d));
// }
}
package com.yeejoin.amos.iec104.tcp.entity;
import java.io.IOException;
import io.netty.buffer.ByteBuf;
public class IeQualifierOfInterrogation extends InformationElement {
private final int value;
public IeQualifierOfInterrogation(int value) {
this.value = value;
}
public IeQualifierOfInterrogation(ByteBuf is) throws IOException {
value = (is.readByte() & 0xff);
}
@Override
public int encode(byte[] buffer, int i) {
buffer[i] = (byte) value;
return 1;
}
public int getValue() {
return value;
}
@Override
public String toString() {
return "Qualifier of interrogation: " + value;
}
}
package com.yeejoin.amos.iec104.tcp.entity;
import java.io.IOException;
import io.netty.buffer.ByteBuf;
import net.sf.json.JSONObject;
/**
* 品质描述
*
*/
public class IeQuality extends IeAbstractQuality {
public IeQuality(boolean overflow, boolean blocked, boolean substituted, boolean notTopical, boolean invalid) {
super(blocked, substituted, notTopical, invalid);
if (overflow) {
value |= 0x01;
}
}
IeQuality(ByteBuf is) throws IOException {
super(is);
}
public boolean isOverflow() {
return (value & 0x01) == 0x01;
}
@Override
public String toString() {
return "品质描述, 溢出: " + isOverflow() + ", " + super.toString();
}
public JSONObject toJson() {
JSONObject json = super.toJson();
json.put("isOverflow", isOverflow());
return json;
}
}
package com.yeejoin.amos.iec104.tcp.entity;
import java.io.IOException;
import io.netty.buffer.ByteBuf;
/**
* 类型标识,测量值,短浮点数
* 遥测
*/
public class IeShortFloat extends InformationElement {
private final float value;
public IeShortFloat(float value) {
this.value = value;
}
public IeShortFloat(ByteBuf is) throws IOException {
value = Float.intBitsToFloat((is.readByte() & 0xff) | ((is.readByte() & 0xff) << 8)
| ((is.readByte() & 0xff) << 16) | ((is.readByte() & 0xff) << 24));
}
@Override
public int encode(byte[] buffer, int i) {
int tempVal = Float.floatToIntBits(value);
buffer[i++] = (byte) tempVal;
buffer[i++] = (byte) (tempVal >> 8);
buffer[i++] = (byte) (tempVal >> 16);
buffer[i] = (byte) (tempVal >> 24);
return 4;
}
public float getValue() {
return value;
}
@Override
public String toString() {
return "短浮点数值: " + value;
}
}
package com.yeejoin.amos.iec104.tcp.entity;
import java.io.IOException;
import io.netty.buffer.ByteBuf;
import net.sf.json.JSONObject;
/**
* 单点信息
*
*/
public class IeSinglePointWithQuality extends IeAbstractQuality {
public IeSinglePointWithQuality(boolean on, boolean blocked, boolean substituted, boolean notTopical,
boolean invalid) {
super(blocked, substituted, notTopical, invalid);
if (on) {
value |= 0x01;
}
}
public IeSinglePointWithQuality(ByteBuf is) throws IOException {
super(is);
}
public boolean isOn() {
return (value & 0x01) == 0x01;
}
@Override
public String toString() {
return "单点, 是否开闸: " + isOn() + ", " + super.toString();
}
public JSONObject toJson() {
JSONObject json = super.toJson();
json.put("isOn", isOn());
return json;
}
}
/*
* Copyright 2014-17 Fraunhofer ISE
*
* This file is part of j60870.
* For more information visit http://www.openmuc.org
*
* j60870 is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* j60870 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with j60870. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.yeejoin.amos.iec104.tcp.entity;
public abstract class InformationElement {
public abstract int encode(byte[] buffer, int i);
}
package com.yeejoin.amos.iec104.tcp.entity;
import java.io.IOException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import io.netty.buffer.ByteBuf;
/**
*信息体对象
*
*/
public class InformationObject {
private Log log = LogFactory.getLog(InformationObject.class);
private int informationObjectAddress;
private final InformationElement[][] informationElements;
public InformationObject(int informationObjectAddress, InformationElement[][] informationElements) {
this.informationObjectAddress = informationObjectAddress;
this.informationElements = informationElements;
}
public InformationObject(ByteBuf is, int typeId, int numberOfSequenceElements)
throws IOException {
this.informationObjectAddress = (is.readByte() & 0xff) + ((is.readByte() & 0xff) << 8)
+ ((is.readByte() & 0xff) << 16);
switch (typeId) {
// 1 单点遥信
case 1:
informationElements = new InformationElement[numberOfSequenceElements][1];
for (int i = 0; i < numberOfSequenceElements; i++) {
informationElements[i][0] = new IeSinglePointWithQuality(is);
log.debug("1 单点遥信: " + i + "--->" + informationElements[i][0].toString());
}
break;
// 13 浮点型遥测
case 13:
informationElements = new InformationElement[numberOfSequenceElements][2];
for (int i = 0; i < numberOfSequenceElements; i++) {
informationElements[i][0] = new IeShortFloat(is);
informationElements[i][1] = new IeQuality(is);
log.debug("13 浮点型遥测1: " + i + "--->" + informationElements[i][0].toString());
log.debug("13 浮点型遥测2: " + i + "--->" + informationElements[i][1].toString());
}
break;
// 30 带 CP56Time2a 时标的单点信息
case 30:
informationElements = new InformationElement[numberOfSequenceElements][2];
for (int i = 0; i < numberOfSequenceElements; i++) {
informationElements[i][0] = new IeSinglePointWithQuality(is);
informationElements[i][1] = new IeCP56Time2a(is);
log.debug("30 带 CP56Time2a 时标的单点信息 值: " + i + "--->" + informationElements[i][0].toString());
log.debug("30 带 CP56Time2a 时标的单点信息 时间: " + i + "--->" + ((IeCP56Time2a)informationElements[i][1]).getFormatDate("yyyy-MM-dd HH:mm:ss"));
}
break;
// 31 带 CP56Time2a 时标的双点信息
case 31:
informationElements = new InformationElement[numberOfSequenceElements][3];
for (int i = 0; i < numberOfSequenceElements; i++) {
informationElements[i][0] = new IeSinglePointWithQuality(is);
informationElements[i][1] = new IeSinglePointWithQuality(is);
informationElements[i][2] = new IeCP56Time2a(is);
log.debug("31 带 CP56Time2a 时标的单点信息 值1: " + i + "--->" + informationElements[i][0].toString());
log.debug("31 带 CP56Time2a 时标的单点信息 值2: " + i + "--->" + informationElements[i][1].toString());
log.debug("31 带 CP56Time2a 时标的单点信息 时间: " + i + "--->" + ((IeCP56Time2a)informationElements[i][2]).getFormatDate("yyyy-MM-dd HH:mm:ss"));
}
break;
// 100 总召
case 100:
informationElements = new InformationElement[][] { { new IeQualifierOfInterrogation(is) } };
log.debug("100 总召: " + informationElements[0][0].toString());
break;
case 103:
informationElements = new InformationElement[][] { { new IeQualifierOfInterrogation(is) } };
log.debug("103 总召: " + informationElements[0][0].toString());
is.clear();
break;
default:
is.clear();
throw new IOException(
"无法转换信息对象,由于类型标识未知: " + typeId);
}
}
public int encode(byte[] buffer, int i) {
int origi = i;
buffer[i++] = (byte) informationObjectAddress;
buffer[i++] = (byte) (informationObjectAddress >> 8);
buffer[i++] = (byte) (informationObjectAddress >> 16);
for (InformationElement[] informationElementCombination : informationElements) {
for (InformationElement informationElement : informationElementCombination) {
i += informationElement.encode(buffer, i);
}
}
return i - origi;
}
public int getInformationObjectAddress() {
return informationObjectAddress;
}
/**
* 信息元素
*
* @return 信息元素二维数组.
*/
public InformationElement[][] getInformationElements() {
return informationElements;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder("IOA: " + informationObjectAddress);
if (informationElements.length > 1) {
int i = 1;
for (InformationElement[] informationElementSet : informationElements) {
builder.append("\n信息体元素集 " + i + ":");
for (InformationElement informationElement : informationElementSet) {
builder.append("\n");
builder.append(informationElement.toString());
}
i++;
}
}
else {
for (InformationElement[] informationElementSet : informationElements) {
for (InformationElement informationElement : informationElementSet) {
builder.append("\n");
builder.append(informationElement.toString());
}
}
}
return builder.toString();
}
}
package com.yeejoin.amos.iec104.tcp.entity;
public class ServerData {
private Apdu apdu;
private String serverId;
public Apdu getApdu() {
return apdu;
}
public void setApdu(Apdu apdu) {
this.apdu = apdu;
}
public String getServerId() {
return serverId;
}
public void setServerId(String serverId) {
this.serverId = serverId;
}
}
package com.yeejoin.amos.iec104.tcp.entity;
public class YXObject {
private int infomationAddress;
private int status;
public int getInfomationAddress() {
return infomationAddress;
}
public void setInfomationAddress(int infomationAddress) {
this.infomationAddress = infomationAddress;
}
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
}
package com.yeejoin.amos.iec104.tcp.server;
import java.net.InetSocketAddress;
import org.apache.log4j.Logger;
import com.yeejoin.amos.iec104.tcp.IEC104Decoder;
import com.yeejoin.amos.iec104.tcp.IEC104Encoder;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.socket.SocketChannel;
public class IEC104ChannelInitalizer extends ChannelInitializer<SocketChannel>{
private String serviceId;
public IEC104ChannelInitalizer(String serviceId) {
this.serviceId = serviceId;
}
@Override
protected void initChannel(SocketChannel channel) throws Exception {
InetSocketAddress s = channel.remoteAddress();
Logger.getLogger(this.getClass()).debug("client channel:" + s.toString());
// 空闲状态助手
// channel.pipeline().addLast(new IdleStateHandler(15, 40, 60, TimeUnit.SECONDS));
// 104报文解码器
channel.pipeline().addLast(new IEC104Decoder(serviceId));
// 104apdu处理类
channel.pipeline().addLast(new IEC104ServerHandler());
// 104编码发送处理类
channel.pipeline().addLast(new IEC104Encoder(serviceId));
}
}
package com.yeejoin.amos.iec104.tcp.server;
import com.yeejoin.amos.connect.dao.entity.ConfigVo;
import org.apache.log4j.Logger;
import com.yeejoin.amos.iec104.business.service.intfc.IConfService;
import com.yeejoin.amos.iec104.context.FireAutoIntfContext;
import com.yeejoin.amos.iec104.exception.YeeException;
import com.yeejoin.amos.op.core.util.ApplicationConfig;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
public class IEC104Server {
/**
* boss线程池
*/
private EventLoopGroup bossLoopGroup;
/**
* worker线程池
*/
private EventLoopGroup workLoogGroup;
/**
* server配置
*/
private ApplicationConfig applicationConfig;
/**
* ChannelFuture
*/
private ChannelFuture customerChannelFuture;
/**
* 监听端口
*/
private int port;
private IEC104ChannelInitalizer channelInitalizer = null;
private Channel serverChannel;
/**
* 运行tcp服务
*/
public void start() {
Thread nettyServer = new Thread(() -> {
try {
// 创建一个serverbootstrap实例
ServerBootstrap serverBootstrap = new ServerBootstrap();
// BOSS线程池
bossLoopGroup = new NioEventLoopGroup(1);
// CPU个数
int processorsNumber = Runtime.getRuntime().availableProcessors();
// worker线程池
workLoogGroup = new NioEventLoopGroup(processorsNumber * 2);
// 指定 boss线程池、worker线程池
serverBootstrap.group(bossLoopGroup, workLoogGroup);
// 指定使用NIO传输Channel
serverBootstrap.channel(NioServerSocketChannel.class);
// 设置option
/***
* BACKLOG用于构造服务端套接字ServerSocket对象,标识当服务器请求处理线程全满时,用于临时存放已完成三次握手的请求的队列的最大长度。
* 如果未设置或所设置的值小于1,Java将使用默认值50。
*/
String backlog = applicationConfig.getParamValueStr("so.backlog");
serverBootstrap.option(ChannelOption.SO_BACKLOG, Integer.valueOf(backlog));
serverBootstrap.childOption(ChannelOption.SO_KEEPALIVE, true);
// 设置连接超时时间30秒
serverBootstrap.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 30000);
// 设置ChannelHandler
IConfService confService = (IConfService) FireAutoIntfContext.getInstance().getBean(IConfService.class);
ConfigVo client = confService.getServerByPort(port+"");
channelInitalizer = new IEC104ChannelInitalizer(client.getServiceId());
serverBootstrap.childHandler(channelInitalizer);
// 异步的绑定服务器,sync()一直等到绑定完成:绑定端口
// customerChannelFuture = serverBootstrap.bind("100.100.100.90", port).sync();
customerChannelFuture = serverBootstrap.bind(port).sync();
// 将ServerChannel保存下来
serverChannel = customerChannelFuture.channel();
Logger.getLogger(this.getClass()).debug("iec104 TCP服务启动成功");
// 阻塞至channel关闭
Logger.getLogger(this.getClass()).error("service wait close");
serverChannel.closeFuture().sync();
} catch (Exception e) {
Logger.getLogger(this.getClass()).error(e);
throw new YeeException("run gateway netty server error!", e, 1004001);
} finally {
// 优雅关闭server线程及相关资源
Logger.getLogger(this.getClass()).error("service is close");
workLoogGroup.shutdownGracefully();
bossLoopGroup.shutdownGracefully();
}
});
nettyServer.setName("netty-server-thread" + port);
nettyServer.setDaemon(true);
nettyServer.start();
}
/**
* 停止tcp服务
*/
public void stop() {
try {
customerChannelFuture.channel().closeFuture().sync();
} catch (Exception e) {
Logger.getLogger(this.getClass()).error(e);
} finally {
bossLoopGroup.shutdownGracefully();
workLoogGroup.shutdownGracefully();
}
}
public ApplicationConfig getApplicationConfig() {
return applicationConfig;
}
public void setApplicationConfig(ApplicationConfig applicationConfig) {
this.applicationConfig = applicationConfig;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
public void close() {
customerChannelFuture.channel().close();
customerChannelFuture = null;
}
}
package com.yeejoin.amos.iec104.tcp.server;
import org.springframework.util.ObjectUtils;
import com.yeejoin.amos.iec104.tcp.entity.Apdu;
import com.yeejoin.amos.iec104.tcp.server.session.Session;
import com.yeejoin.amos.iec104.tcp.server.session.SessionManager;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
public class IEC104ServerHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
super.channelRead(ctx, msg);
if (msg instanceof Apdu) {
Apdu apdu = (Apdu) msg;
receive(apdu, ctx);
}
}
private void receive(Apdu apdu, ChannelHandlerContext ctx) {
Session session = SessionManager.getInstance().getSession(ctx);
if (ObjectUtils.isEmpty(session)) {
session = SessionManager.getInstance().createSession(ctx);
}
session.process(apdu);
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
super.channelInactive(ctx);
SessionManager.getInstance().removeSession(ctx);
}
}
package com.yeejoin.amos.iec104.tcp.server.connector;
import io.netty.channel.ChannelHandlerContext;
public class TcpConnector {
private ChannelHandlerContext ctx;
public TcpConnector(ChannelHandlerContext ctx) {
this.ctx = ctx;
}
/**
* 发送数据 ----待开发
* @param apdu
*/
public void sendMessage(String strBytes) {
ctx.channel().writeAndFlush(strBytes, ctx.newPromise());
}
public void closeConnect() {
this.ctx.close();
}
public ChannelHandlerContext getCtx() {
return ctx;
}
public void setCtx(ChannelHandlerContext ctx) {
this.ctx = ctx;
}
}
package com.yeejoin.amos.iec104.tcp.server.session;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Predicate;
import com.yeejoin.amos.connect.dao.entity.ConfigVo;
import com.yeejoin.amos.connect.dao.entity.PointConfigVo;
import org.apache.log4j.Logger;
import org.springframework.beans.BeanUtils;
import org.springframework.util.ObjectUtils;
import com.yeejoin.amos.iec104.business.service.intfc.IConfService;
import com.yeejoin.amos.iec104.business.service.intfc.IPointConfigService;
import com.yeejoin.amos.iec104.context.FireAutoIntfContext;
import com.yeejoin.amos.iec104.tcp.entity.Apdu;
import com.yeejoin.amos.iec104.tcp.entity.Asdu;
import com.yeejoin.amos.iec104.tcp.utils.ChangeUtils;
import com.yeejoin.amos.iec104.tcp.utils.GenerateDate;
import io.netty.channel.ChannelHandlerContext;
public class Session {
ChannelHandlerContext ctx;
private String commonAddr = "";
private String infoAddr = "";
private String channelNo = "";
int receiveNum = 0;
int sendNum = 0;
long timeRecorder = 0;
private long recordTime = 0;
private ReentrantLock serialLock = new ReentrantLock();
// private Semaphore secruitingSemaphore = new Semaphore(1);
// boolean startCommunication = false;
boolean stopCommunication = false;
boolean startRecruiting = false;
CountDownLatch latch;
private Semaphore recruitingSemaphore = new Semaphore(1);
boolean recIpackate = false;
private BlockingQueue<Apdu> handleBlockingRecQueue = new LinkedBlockingQueue<Apdu>();
private BlockingQueue<String> handleBlockingSendQueue = new LinkedBlockingQueue<String>();
private BlockingQueue<PointConfigVo> SOEBlockingRecQueue = new LinkedBlockingQueue<PointConfigVo>();
private BlockingQueue<PointConfigVo> SECBlockingRecQueue = new LinkedBlockingQueue<PointConfigVo>();
ScheduledExecutorService test_Communication = null;
ScheduledExecutorService eecruiting_Communication = null;
ScheduledExecutorService send_Communication = null;
ScheduledExecutorService ack_Communication = null;
ScheduledExecutorService rec_Communication = null;
ScheduledExecutorService soe_Communication = null;
ScheduledExecutorService sec_Communication = null;
private IPointConfigService pointConfigService;
private IConfService confService;
public Session(ChannelHandlerContext ctx) {
this.ctx = ctx;
pointConfigService = (IPointConfigService) FireAutoIntfContext.getInstance().getBean(IPointConfigService.class);
confService = (IConfService) FireAutoIntfContext.getInstance().getBean(IConfService.class);
InetSocketAddress socket = (InetSocketAddress) this.ctx.channel().localAddress();
ConfigVo client = confService.getServerByPort(socket.getPort()+"");
channelNo = client.getChannelNo();
addTestlistener();
addSendDatalistener();
addRecruitingDatalistener();
addACKDatalistener();
addRecDatalistener();
addSOEDataListener();
addSECDataListener();
}
public void addSOE(PointConfigVo soe) {
SOEBlockingRecQueue.add(soe);
}
public void addSEC(PointConfigVo soe) {
SECBlockingRecQueue.add(soe);
}
private void addSECDataListener() {
sec_Communication = Executors.newSingleThreadScheduledExecutor();
// 第二个参数为首次执行的延时时间,第三个参数为定时执行的间隔时间
sec_Communication.execute(sec_runnable);;
}
Runnable sec_runnable = new Runnable() {
@Override
public void run() {
while(!stopCommunication) {
try {
PointConfigVo vo = SECBlockingRecQueue.take();
// int len = 0;
PointConfigVo p = null;
StringBuffer strAsduDataBytes = new StringBuffer();
// int sendCount = 0;
// do {
if (!ObjectUtils.isEmpty(vo)) {
p = new PointConfigVo();
BeanUtils.copyProperties(vo, p);
vo = null;
}
// else {
// p = SECBlockingRecQueue.poll();
// }
if (ObjectUtils.isEmpty(p)) {
break;
}
if ("yc".equals(p.getPointType())) {
p.setOriginatorAddress(p.getOriginatorAddress() + 0x4000);
}
strAsduDataBytes.append(ChangeUtils.encodeInfomationAddress(p.getOriginatorAddress())); // 信息体地址,3个字节
if (p.getOriginatorAddress() < 0x4000) {
String status = Integer.toHexString(Integer.valueOf(p.getValue()));
status = status.length() > 1? status : "0".concat(status);
strAsduDataBytes.append(status); // 点状态 正常 合格 不合格 漏检
// len++;
} else {
String sendData = "";
byte[] elements = ChangeUtils.float2byte(Float.parseFloat(p.getValue()));
sendData = sendData + ChangeUtils.toHexString(elements);
sendData = sendData + Integer.toHexString(0x80 | 0);
strAsduDataBytes.append(sendData); // 点状态 正常 合格 不合格 漏检
// len += 4;
}
// sendCount++;
// } while(len < 240);
StringBuffer strAsduBytes = new StringBuffer();
if ("yc".equals(p.getPointType())) {
strAsduBytes.append("0D");
} else {
strAsduBytes.append("01");
}
String strSoeCount = Integer.toHexString(1);
strAsduBytes.append(strSoeCount.length() > 1? strSoeCount : "0".concat(strSoeCount)); // 可变结构限定词,1个SEC
strAsduBytes.append("0300"); // 传送原因,2个字节,3-表突发事件
strAsduBytes.append(commonAddr); // 公共地址,2个字节
strAsduBytes.append(strAsduDataBytes);
String dataUnitLen = Integer.toHexString(strAsduBytes.toString().replace(" ", "").length() / 2 + 4);
String length = dataUnitLen.length() > 1 ? dataUnitLen : "0".concat(dataUnitLen);
serialLock.lock();
byte[] sendNumBytes = new byte[2];
byte[] recNumBytes = new byte[2];
sendNumBytes[0] = (byte) (sendNum << 1);
sendNumBytes[1] = (byte) (sendNum >> 7);
recNumBytes[0] = (byte) (receiveNum << 1);
recNumBytes[1] = (byte) (receiveNum >> 7);
String recStr = ChangeUtils.toHexString(recNumBytes);
String sendStr = ChangeUtils.toHexString(sendNumBytes);
sendNum ++;
String dataStr = "68" + length + sendStr + recStr + strAsduBytes.toString().replace(" ", "");
Logger.getLogger(this.getClass()).debug("SEC 报文为: " + dataStr);
handleBlockingSendQueue.add(dataStr);
serialLock.unlock();
} catch (Exception e) {
e.printStackTrace();
}
}
}
};
private void addSOEDataListener() {
soe_Communication = Executors.newSingleThreadScheduledExecutor();
// 第二个参数为首次执行的延时时间,第三个参数为定时执行的间隔时间
soe_Communication.execute(soe_runnable);;
}
Runnable soe_runnable = new Runnable() {
@Override
public void run() {
while(!stopCommunication) {
try {
PointConfigVo vo = SOEBlockingRecQueue.take();
int len = 0;
PointConfigVo p = null;
StringBuffer strAsduDataBytes = new StringBuffer();
int sendCount = 0;
do {
if (!ObjectUtils.isEmpty(vo)) {
p = new PointConfigVo();
BeanUtils.copyProperties(vo, p);
vo = null;
} else {
p = SOEBlockingRecQueue.poll();
}
if (ObjectUtils.isEmpty(p)) {
break;
}
strAsduDataBytes.append(ChangeUtils.encodeInfomationAddress(p.getOriginatorAddress())); // 信息体地址,3个字节
String status = Integer.toHexString(Integer.valueOf(p.getValue()));
status = status.length() > 1? status : "0".concat(status);
strAsduDataBytes.append(status); // 点状态 正常 合格 不合格 漏检
strAsduDataBytes.append(GenerateDate.getCP56Time2a());
len += 4;
sendCount++;
} while(len < 240);
StringBuffer strAsduBytes = new StringBuffer("1E");
String strSoeCount = Integer.toHexString(sendCount);
strAsduBytes.append(strSoeCount.length() > 1? strSoeCount : "0".concat(strSoeCount)); // 可变结构限定词,1个SOE
strAsduBytes.append("0300"); // 传送原因,2个字节,3-表突发事件
strAsduBytes.append(commonAddr); // 公共地址,2个字节
strAsduBytes.append(strAsduDataBytes.toString());
String dataUnitLen = Integer.toHexString(strAsduBytes.toString().replace(" ", "").length() / 2 + 4);
String length = dataUnitLen.length() > 1 ? dataUnitLen : "0".concat(dataUnitLen);
serialLock.lock();
byte[] sendNumBytes = new byte[2];
byte[] recNumBytes = new byte[2];
sendNumBytes[0] = (byte) (sendNum << 1);
sendNumBytes[1] = (byte) (sendNum >> 7);
recNumBytes[0] = (byte) (receiveNum << 1);
recNumBytes[1] = (byte) (receiveNum >> 7);
String recStr = ChangeUtils.toHexString(recNumBytes);
String sendStr = ChangeUtils.toHexString(sendNumBytes);
sendNum ++;
String dataStr = "68" + length + sendStr + recStr + strAsduBytes.toString().replace(" ", "");
Logger.getLogger(this.getClass()).debug("soe 报文为: " + dataStr);
handleBlockingSendQueue.add(dataStr);
serialLock.unlock();
} catch (Exception e) {
e.printStackTrace();
}
}
}
};
private void addRecDatalistener() {
rec_Communication = Executors.newSingleThreadScheduledExecutor();
// 第二个参数为首次执行的延时时间,第三个参数为定时执行的间隔时间
rec_Communication.execute(data_runnable);;
}
private void addACKDatalistener() {
timeRecorder = new Date().getTime();
ack_Communication = Executors.newSingleThreadScheduledExecutor();
// 第二个参数为首次执行的延时时间,第三个参数为定时执行的间隔时间
ack_Communication.scheduleAtFixedRate(ack_runnable, 1, 1, TimeUnit.SECONDS);
}
Runnable ack_runnable = new Runnable() {
@Override
public void run() {
long currentTime = new Date().getTime();
if (recIpackate && ((currentTime - timeRecorder) / 1000) > 3) {
recIpackate = false;
byte[] recNum = new byte[2];
recNum[0] = (byte) (receiveNum << 1);
recNum[1] = (byte) (receiveNum >> 7);
String recStr = ChangeUtils.toHexString(recNum);
ctx.channel().writeAndFlush("68040100" + recStr);
}
}
};
private void addRecruitingDatalistener() {
// latch = new CountDownLatch(1);
eecruiting_Communication = Executors.newSingleThreadScheduledExecutor();
// 第二个参数为首次执行的延时时间,第三个参数为定时执行的间隔时间
eecruiting_Communication.execute(Recruiting_runnable);;
}
private void addSendDatalistener() {
send_Communication = Executors.newSingleThreadScheduledExecutor();
// 第二个参数为首次执行的延时时间,第三个参数为定时执行的间隔时间
send_Communication.execute(send_runnable);;
}
Runnable send_runnable = new Runnable() {
@Override
public void run() {
while(!stopCommunication) {
try {
String data = handleBlockingSendQueue.take();
ctx.channel().writeAndFlush(data.replace(" ", ""));
recIpackate = false;
} catch (Exception e) {
e.printStackTrace();
}
}
}
};
public void respondTiming(Apdu apdu) {
Asdu asdu = apdu.getAsdu();
byte[] send = new byte[2];
byte[] rec = new byte[2];
serialLock.lock();
send[0] = (byte) (sendNum << 1);
send[1] = (byte) (sendNum >> 7);
rec[0] = (byte) (receiveNum << 1);
rec[1] = (byte) (receiveNum >> 7);
String recStr = ChangeUtils.toHexString(rec);
String sendStr = ChangeUtils.toHexString(send);
sendNum ++;
serialLock.unlock();
String jihuoQueRen = "6814" +
sendStr +
recStr +
"67010700" +
ChangeUtils.encodeCommonAddress(asdu.getCommonAddress()) +
ChangeUtils.encodeInfomationAddress(asdu.getOriginatorAddress()) +
GenerateDate.getCP56Time2a();
commonAddr = ChangeUtils.encodeCommonAddress(asdu.getCommonAddress());
infoAddr = ChangeUtils.encodeCommonAddress(asdu.getOriginatorAddress());
recIpackate = false;
handleBlockingSendQueue.add(jihuoQueRen.replace(" ", ""));
}
Runnable data_runnable = new Runnable() {
@Override
public void run() {
while(!stopCommunication) {
try {
Apdu apdu = handleBlockingRecQueue.take();
Asdu asdu = apdu.getAsdu();
if (asdu.getTypeId() == 100) { //服务端接收处理客户端总招请求
respondRecruiting(apdu);
} else if (asdu.getTypeId() == 103) { //服务端接收处理客户端总招请求
respondTiming(apdu);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
};
Runnable Recruiting_runnable = new Runnable() {
@Override
public void run() {
while(!stopCommunication) {
try {
// latch.await();
recruitingSemaphore.acquire();
} catch (Exception e) {
}
Logger.getLogger(this.getClass()).info("start process Recruiting 1");
while(startRecruiting) {
Logger.getLogger(this.getClass()).info("start process Recruiting 2");
try {
List<PointConfigVo> yx = pointConfigService.getAllYXPointData(channelNo);
if (!ObjectUtils.isEmpty(yx) && yx.size() > 0) {
Logger.getLogger(this.getClass()).info("start process yx Recruiting");
recIpackate = false;
String infomationAddress = ChangeUtils.encodeInfomationAddress(yx.get(0).getOriginatorAddress());
Iterator<PointConfigVo> it = yx.iterator();
do {
int len = 0;
String sendData = "";
do {
PointConfigVo p = it.next();
if (ObjectUtils.isEmpty(infomationAddress)) {
infomationAddress = ChangeUtils.encodeInfomationAddress(p.getOriginatorAddress());
}
String status = "";
String value = ObjectUtils.isEmpty(p.getValue()) ? "0" : p.getValue();
if (p.getInvalid()) {
status = Integer.toHexString(Integer.valueOf(value) | 0x80);
} else {
status = Integer.toHexString(Integer.valueOf(value));
}
status = status.length() > 1? status : "0".concat(status);
sendData = sendData + status;
len++;
} while(it.hasNext() && len < 126);
StringBuffer strAsduBytes = new StringBuffer("01"); //
strAsduBytes.append(Integer.toHexString(0x80 | len)); //
strAsduBytes.append("1400"); //
strAsduBytes.append(commonAddr); //
strAsduBytes.append(infomationAddress); // 信息体地址,3个字节
infomationAddress = null;
strAsduBytes.append(sendData);
String dataUnitLen = Integer.toHexString(strAsduBytes.toString().replace(" ", "").length() / 2 + 4);
String length = dataUnitLen.length() > 1 ? dataUnitLen : "0".concat(dataUnitLen);
serialLock.lock();
byte[] sendNumBytes = new byte[2];
byte[] recNumBytes = new byte[2];
sendNumBytes[0] = (byte) (sendNum << 1);
sendNumBytes[1] = (byte) (sendNum >> 7);
recNumBytes[0] = (byte) (receiveNum << 1);
recNumBytes[1] = (byte) (receiveNum >> 7);
String recStr = ChangeUtils.toHexString(recNumBytes);
String sendStr = ChangeUtils.toHexString(sendNumBytes);
sendNum ++;
String dataStr = "68" + length + sendStr + recStr + strAsduBytes.toString().replace(" ", "");
Logger.getLogger(this.getClass()).debug("yx 报文为: " + dataStr);
handleBlockingSendQueue.add(dataStr);
serialLock.unlock();
} while(it.hasNext());
}
List<PointConfigVo> yc = pointConfigService.getAllYCPointData(channelNo);
if (!ObjectUtils.isEmpty(yc) && yc.size() > 0) {
Logger.getLogger(this.getClass()).info("start process yc Recruiting");
recIpackate = false;
String infomationAddress = ChangeUtils.encodeInfomationAddress(yc.get(0).getOriginatorAddress() + 0x4000);
Iterator<PointConfigVo> it = yc.iterator();
do {
int len = 0;
String sendData = "";
do {
PointConfigVo p = it.next();
String value = ObjectUtils.isEmpty(p.getValue()) ? "0" : p.getValue();
if (ObjectUtils.isEmpty(infomationAddress)) {
infomationAddress = ChangeUtils.encodeInfomationAddress(p.getOriginatorAddress() + 0x4000);
}
byte[] elements = ChangeUtils.float2byte(Float.parseFloat(value));
sendData = sendData + " " + ChangeUtils.toHexString(elements);
sendData = sendData + Integer.toHexString(0x80 | 0);
len ++;
} while(it.hasNext() && len < 120);
StringBuffer strAsduBytes = new StringBuffer("0D"); //
strAsduBytes.append(Integer.toHexString(0x80 | len)); //
strAsduBytes.append("1400"); //
strAsduBytes.append(commonAddr); //
strAsduBytes.append(infomationAddress); // 信息体地址,3个字节
infomationAddress = null;
strAsduBytes.append(sendData);
String dataUnitLen = Integer.toHexString(strAsduBytes.toString().replace(" ", "").length() / 2 + 4);
String length = dataUnitLen.length() > 1 ? dataUnitLen : "0".concat(dataUnitLen);
serialLock.lock();
byte[] sendNumBytes = new byte[2];
byte[] recNumBytes = new byte[2];
sendNumBytes[0] = (byte) (sendNum << 1);
sendNumBytes[1] = (byte) (sendNum >> 7);
recNumBytes[0] = (byte) (receiveNum << 1);
recNumBytes[1] = (byte) (receiveNum >> 7);
String recStr = ChangeUtils.toHexString(recNumBytes);
String sendStr = ChangeUtils.toHexString(sendNumBytes);
sendNum ++;
String dataStr = "68" + length + sendStr + recStr + strAsduBytes.toString();
handleBlockingSendQueue.add(dataStr.replace(" ", ""));
recIpackate = false;
serialLock.unlock();
} while(it.hasNext());
}
serialLock.lock();
byte[] sendNumBytes = new byte[2];
byte[] recNumBytes = new byte[2];
sendNumBytes[0] = (byte) (sendNum << 1);
sendNumBytes[1] = (byte) (sendNum >> 7);
recNumBytes[0] = (byte) (receiveNum << 1);
recNumBytes[1] = (byte) (receiveNum >> 7);
String recStr = ChangeUtils.toHexString(recNumBytes);
String sendStr = ChangeUtils.toHexString(sendNumBytes);
sendNum ++;
serialLock.unlock();
//发送总招 激活终止
String jihuoStop = "680E" +
sendStr+
recStr +
"64010A00" +
commonAddr +
"000000" +
"14";
handleBlockingSendQueue.add(jihuoStop.replace(" ", ""));
} catch (Exception e) {
e.printStackTrace();
}
startRecruiting = false;
}
}
}
};
protected void respondRecruiting(Apdu apdu) {
byte[] sendNumBytes = new byte[2];
byte[] recNumBytes = new byte[2];
try {
serialLock.lock();
sendNumBytes[0] = (byte) (sendNum << 1);
sendNumBytes[1] = (byte) (sendNum >> 7);
recNumBytes[0] = (byte) (receiveNum << 1);
recNumBytes[1] = (byte) (receiveNum >> 7);
String recStr = ChangeUtils.toHexString(recNumBytes);
String sendStr = ChangeUtils.toHexString(sendNumBytes);
sendNum ++;
if (apdu.getAsdu().getCauseOfTransmission() == 6) {
Asdu asdu = apdu.getAsdu();
String jihuoQueRen = "680E" +
sendStr +
recStr +
"64010700" +
ChangeUtils.encodeCommonAddress(asdu.getCommonAddress()) +
ChangeUtils.encodeInfomationAddress(asdu.getOriginatorAddress()) +
"14";
startRecruiting = true;
// latch.countDown();
recruitingSemaphore.release();
handleBlockingSendQueue.add(jihuoQueRen.replace(" ", ""));
recIpackate = false;
//secruitingSemaphore.release(); // 释放一个许可
}
} catch (Exception e) {
e.printStackTrace();
} finally {
serialLock.unlock();
}
}
public void processPoints(List<PointConfigVo> points) {
change(points); //变为消息
soe(points);
}
public static List<PointConfigVo> filter(List<PointConfigVo> points, Predicate<PointConfigVo> condition) {
List<PointConfigVo> results = new ArrayList<PointConfigVo>();
for (PointConfigVo c : points) {
if(condition.test(c)) {
results.add(c);
}
}
return results;
}
private void soe(List<PointConfigVo> points) {
List list = filter(points, (c) -> c.getOriginatorAddress() < 0x4000);
if (list.size() <= 0) return;
Iterator<PointConfigVo> it = list.iterator();
//处理遥信数据
do {
StringBuffer strAsduBytes = new StringBuffer("1E");
StringBuffer strAsduDataBytes = new StringBuffer();
int byteNumber = 0;
int soeNumber = 0;
do {
PointConfigVo point = it.next();
strAsduDataBytes.append(ChangeUtils.encodeInfomationAddress(point.getOriginatorAddress())); // 信息体地址,3个字节
String status = Integer.toHexString(Integer.valueOf(point.getValue()));
status = status.length() > 1? status : "0".concat(status);
strAsduDataBytes.append(status); // 点状态 正常 合格 不合格 漏检
strAsduDataBytes.append(GenerateDate.getCP56Time2a());
byteNumber += 8;
soeNumber++;
} while(it.hasNext() && byteNumber < 230);
strAsduBytes.append((soeNumber+"").length() > 1? (soeNumber+"") : "0".concat(soeNumber+"")); // 可变结构限定词,1个SOE
strAsduBytes.append("0300"); // 传送原因,2个字节,3-表突发事件
strAsduBytes.append(commonAddr); // 公共地址,2个字节
strAsduBytes.append(strAsduDataBytes);
int apduLen = strAsduBytes.toString().replace(" ", "").length() / 2 + 4;
String len = Integer.toHexString(apduLen).length() > 1? Integer.toHexString(apduLen): "0".concat(Integer.toHexString(apduLen));
serialLock.lock();
byte[] sendNumBytes = new byte[2];
byte[] recNumBytes = new byte[2];
sendNumBytes[0] = (byte) (sendNum << 1);
sendNumBytes[1] = (byte) (sendNum >> 7);
recNumBytes[0] = (byte) (receiveNum << 1);
recNumBytes[1] = (byte) (receiveNum >> 7);
String recStr = ChangeUtils.toHexString(recNumBytes);
String sendStr = ChangeUtils.toHexString(sendNumBytes);
sendNum ++;
String soe = "68" + len + sendStr + recStr + strAsduBytes.toString();
handleBlockingSendQueue.add(soe.replace(" ", ""));
serialLock.unlock();
} while(it.hasNext());
}
private void change(List<PointConfigVo> points) {
List yc = filter(points, (c) -> c.getOriginatorAddress() > 0x4000);
List yx = filter(points, (c) -> c.getOriginatorAddress() <= 0x4000);
if (yc.size() > 0) {
//处理遥测数据
Iterator<PointConfigVo> it = yc.iterator();
do {
StringBuffer strAsduBytes = new StringBuffer("01");
StringBuffer strAsduDataBytes = new StringBuffer();
int byteNumber = 0;
int soeNumber = 0;
do {
PointConfigVo point = it.next();
if (validateThreshold(point)) {
strAsduDataBytes.append(ChangeUtils.encodeInfomationAddress(point.getOriginatorAddress())); // 信息体地址,3个字节
byte[] elements = ChangeUtils.float2byte(Float.parseFloat(point.getValue()));
strAsduDataBytes.append(ChangeUtils.toHexString(elements)); //
byteNumber += 4;
soeNumber++;
}
} while(it.hasNext() && byteNumber < 230);
strAsduBytes.append((soeNumber+"").length() > 1? (soeNumber+"") : "0".concat(soeNumber+"")); // 可变结构限定词,1个SOE
strAsduBytes.append("0300"); // 传送原因,2个字节,3-表突发事件
strAsduBytes.append(commonAddr); // 公共地址,2个字节
strAsduBytes.append(strAsduDataBytes);
int apduLen = strAsduBytes.toString().replace(" ", "").length() / 2 + 4;
String len = Integer.toHexString(apduLen).length() > 1? Integer.toHexString(apduLen): "0".concat(Integer.toHexString(apduLen));
serialLock.lock();
byte[] sendNumBytes = new byte[2];
byte[] recNumBytes = new byte[2];
sendNumBytes[0] = (byte) (sendNum << 1);
sendNumBytes[1] = (byte) (sendNum >> 7);
recNumBytes[0] = (byte) (receiveNum << 1);
recNumBytes[1] = (byte) (receiveNum >> 7);
String recStr = ChangeUtils.toHexString(recNumBytes);
String sendStr = ChangeUtils.toHexString(sendNumBytes);
sendNum ++;
String soe = "68" + len + sendStr + recStr + strAsduBytes.toString();
handleBlockingSendQueue.add(soe.replace(" ", ""));
serialLock.unlock();
} while(it.hasNext());
}
if (yx.size() > 0) {
//处理遥信数据
Iterator<PointConfigVo> it = yx.iterator();
//处理遥信数据
do {
StringBuffer strAsduBytes = new StringBuffer("01");
StringBuffer strAsduDataBytes = new StringBuffer();
int byteNumber = 0;
int soeNumber = 0;
do {
PointConfigVo point = it.next();
strAsduDataBytes.append(ChangeUtils.encodeInfomationAddress(point.getOriginatorAddress())); // 信息体地址,3个字节
String status = Integer.toHexString(Integer.valueOf(point.getValue()));
status = status.length() > 1? status : "0".concat(status);
strAsduDataBytes.append(status); // 点状态 正常 合格 不合格 漏检
byteNumber += 8;
soeNumber++;
} while(it.hasNext() && byteNumber < 230);
strAsduBytes.append((soeNumber+"").length() > 1? (soeNumber+"") : "0".concat(soeNumber+"")); // 可变结构限定词,1个SOE
strAsduBytes.append("0300"); // 传送原因,2个字节,3-表突发事件
strAsduBytes.append(commonAddr); // 公共地址,2个字节
strAsduBytes.append(strAsduDataBytes);
int apduLen = strAsduBytes.toString().replace(" ", "").length() / 2 + 4;
String len = Integer.toHexString(apduLen).length() > 1? Integer.toHexString(apduLen): "0".concat(Integer.toHexString(apduLen));
serialLock.lock();
byte[] sendNumBytes = new byte[2];
byte[] recNumBytes = new byte[2];
sendNumBytes[0] = (byte) (sendNum << 1);
sendNumBytes[1] = (byte) (sendNum >> 7);
recNumBytes[0] = (byte) (receiveNum << 1);
recNumBytes[1] = (byte) (receiveNum >> 7);
String recStr = ChangeUtils.toHexString(recNumBytes);
String sendStr = ChangeUtils.toHexString(sendNumBytes);
sendNum ++;
String soe = "68" + len + sendStr + recStr + strAsduBytes.toString();
handleBlockingSendQueue.add(soe.replace(" ", ""));
serialLock.unlock();
} while(it.hasNext());
}
}
private boolean validateThreshold(PointConfigVo point) {
return false;
}
private void addTestlistener() {
test_Communication = Executors.newSingleThreadScheduledExecutor();
// 第二个参数为首次执行的延时时间,第三个参数为定时执行的间隔时间
test_Communication.scheduleAtFixedRate(test_runnable, 0, 1, TimeUnit.SECONDS);
}
Runnable test_runnable = new Runnable() {
@Override
public void run() {
Date date = new Date();
//recordTime;
if (!stopCommunication && ((date.getTime() - recordTime) / 1000) >= 10) {
ctx.channel().writeAndFlush("680443000000");
}
}
};
public void refreshRecordTime() {
Date date = new Date();
this.recordTime = date.getTime();
}
public void process(Apdu apdu) {
if (!validateApdu(apdu)) {
return;
}
refreshRecordTime();
if (apdu.getApciType() == Apdu.ApciType.I_FORMAT) {
//处理I命令
if (ObjectUtils.isEmpty(commonAddr)) {
commonAddr = ChangeUtils.encodeCommonAddress(apdu.getAsdu().getCommonAddress());
}
timeRecorder = new Date().getTime();
recIpackate = true;
handleBlockingRecQueue.add(apdu);
} else if (apdu.getApciType() == Apdu.ApciType.S_FORMAT) {
Logger.getLogger(this.getClass()).warn("返回S确认帧");
if (apdu.getReceiveSeqNumber() != sendNum) {
closeChinnel();
}
} else if (apdu.getApciType() == Apdu.ApciType.STARTDT_ACT) {
sendNum = 0;
receiveNum = 0;
ctx.channel().writeAndFlush("68040B000000");
} else if (apdu.getApciType() == Apdu.ApciType.STOPDT_ACT) {
sendNum = 0;
receiveNum = 0;
ctx.channel().writeAndFlush("680423000000");
} else if (apdu.getApciType() == Apdu.ApciType.TESTFR_ACT) {
ctx.channel().writeAndFlush("680483000000");
} else {
Logger.getLogger(this.getClass()).warn("其他报文:" + apdu.getApciType());
}
}
public boolean validateApdu(Apdu apdu) {
if (apdu.getApciType() == Apdu.ApciType.I_FORMAT) {
if (apdu.getSendSeqNumber() != receiveNum || apdu.getReceiveSeqNumber() != sendNum) {
closeChinnel();
return false;
}
if (receiveNum == apdu.getSendSeqNumber()) {
receiveNum++;
return true;
}
} else if (apdu.getApciType() == Apdu.ApciType.S_FORMAT) {
if (apdu.getReceiveSeqNumber() != sendNum) {
closeChinnel();
return false;
}
}
return true;
}
private void closeChinnel() {
// startCommunication = false;
stopCommunication = false;
startRecruiting = false;
recIpackate = false;
receiveNum = 0;
sendNum = 0;
if (serialLock.isLocked()) {
serialLock.unlock();
serialLock = null;
}
// try {
// secruitingSemaphore = null;
// } catch (Exception e) {
//
// }
ctx.channel().close();
if (test_Communication != null) {
test_Communication.shutdownNow();
test_Communication = null;
}
if (eecruiting_Communication != null) {
eecruiting_Communication.shutdownNow();
eecruiting_Communication = null;
}
if (send_Communication != null) {
send_Communication.shutdownNow();
send_Communication = null;
}
if (ack_Communication != null) {
ack_Communication.shutdownNow();
ack_Communication = null;
}
handleBlockingRecQueue.clear();
handleBlockingSendQueue.clear();
SessionManager.getInstance().removeSession(ctx);
}
}
package com.yeejoin.amos.iec104.tcp.server.session;
import java.net.InetSocketAddress;
import java.util.Collection;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledExecutorService;
import org.apache.log4j.Logger;
import io.netty.channel.ChannelHandlerContext;
public class SessionManager {
private static ConcurrentHashMap<String, Session> Ipsessions = new ConcurrentHashMap<>();
private boolean isDebug = false;
private volatile static SessionManager instance = null;
ScheduledExecutorService service_session = null;
private SessionManager() {}
public static SessionManager getInstance(){
//先检查实例是否存在,如果不存在才进入下面的同步块
if(instance == null){
//同步块,线程安全的创建实例
synchronized(SessionManager.class){
//再次检查实例是否存在,如果不存在才真的创建实例
if(instance == null){
instance = new SessionManager();
}
}
}
return instance;
}
/**
* 创建设备连接session
*/
public Session createSession(ChannelHandlerContext ctx) {
InetSocketAddress socket = (InetSocketAddress) ctx.channel().remoteAddress();
String key = socket.toString();
if (!Ipsessions.containsKey(key)) {
Session session = new Session(ctx);
Ipsessions.put(key, session);
session.refreshRecordTime();
Logger.getLogger(this.getClass()).debug(key + " session created ");
return session;
}
return null;
}
/**
* 更新上次数据连接时间,如果session为空,则创建session
* @param sessionId
* @param ctx
*/
public void updateTimeStamp(ChannelHandlerContext ctx) {
InetSocketAddress socket = (InetSocketAddress) ctx.channel().remoteAddress();
String key = socket.toString();
Session session = Ipsessions.get(key);
if (session != null) {
session.refreshRecordTime();
} else {
createSession(ctx);
}
}
/**
* 移除session
* @param sessionId
*/
public void removeSession(ChannelHandlerContext ctx) {
InetSocketAddress socket = (InetSocketAddress) ctx.channel().remoteAddress();
String key = socket.toString();
Ipsessions.remove(key);
Logger.getLogger(this.getClass()).debug(key + " session is removed ");
}
public boolean containsSession(ChannelHandlerContext ctx) {
InetSocketAddress socket = (InetSocketAddress) ctx.channel().remoteAddress();
String key = socket.toString();
return Ipsessions.containsKey(key);
}
public Session getSession(ChannelHandlerContext ctx) {
InetSocketAddress socket = (InetSocketAddress) ctx.channel().remoteAddress();
String key = socket.toString();
return Ipsessions.get(key);
}
public Collection<Session> getClients() {
return Ipsessions.values();
}
public boolean isDebug() {
return isDebug;
}
public void setDebug(boolean isDebug) {
this.isDebug = isDebug;
}
}
package com.yeejoin.amos.iec104.tcp.utils;
import com.yeejoin.amos.iec104.tcp.entity.IeShortFloat;
public class ChangeUtils {
private static final char[] HEX_CHAR_TABLE = {
'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'
};
public static String toHexString(Byte[] data){
byte[] resultBytes = new byte[data.length];
for(int i =0 ;i<data.length;i++){
resultBytes[i] = data[i];
}
return toHexString(resultBytes);
}
public static String toHexString(byte[] data){
if(data == null || data.length == 0)
return null;
byte[] hex = new byte[data.length * 2];
int index = 0;
for(byte b : data){
int v = b & 0xFF;
hex[index++] = (byte) HEX_CHAR_TABLE[v >>> 4];
hex[index++] = (byte) HEX_CHAR_TABLE[v & 0xF];
}
return new String(hex);
}
public static byte[] hexStringToBytes(String data){
if(data == null || "".equals(data))
return null;
data = data.toUpperCase();
int length = data.length()/2;
char[] dataChars = data.toCharArray();
byte[] byteData = new byte[length];
for (int i = 0;i<length;i++){
int pos = i * 2;
byteData[i] = (byte)(charToByte(dataChars[pos]) << 4 | charToByte(dataChars[pos + 1]));
}
return byteData;
}
public static byte charToByte(char c){
return (byte)"0123456789ABCDEF".indexOf(c);
}
public static String byteAppend(byte[] bytes){
StringBuffer stringBuffer = new StringBuffer();
for (int i=bytes.length-1;i>=0;i--){
stringBuffer.append(String.format("%02d",bytes[i]));
}
return stringBuffer.toString();
}
public static String floatToHexstr(float value){
byte[] buffer = new byte[4];
new IeShortFloat(value).encode(buffer,0);
return toHexString(buffer);
}
public static String encode(float value){
int tempVal = Float.floatToIntBits(value);
byte[] buffer = new byte[4];
buffer[0] = (byte) tempVal;
buffer[1] = (byte) (tempVal >> 8);
buffer[2] = (byte) (tempVal >> 16);
buffer[3] = (byte) (tempVal >> 24);
int[] s = new int[4];
StringBuffer sb = new StringBuffer();
for (int i = 0; i < buffer.length; i++){
s[i] = (buffer[i] & 0xff);
if (Integer.toHexString(s[i]).length() == 1){
sb.append("0" + Integer.toHexString(s[i]) + " ");
}else {
sb.append(Integer.toHexString(s[i]) + " ");
}
}
return sb.toString().toUpperCase();
}
public static String encodeInfomationAddress(int address) {
byte[] buffer = new byte[3];
buffer[0] = (byte) address;
buffer[1] = (byte) (address >> 8);
buffer[2] = (byte) (address >> 16);
int[] s = new int[4];
StringBuffer sb = new StringBuffer();
for (int i = 0; i < buffer.length; i++){
s[i] = (buffer[i] & 0xff);
if (Integer.toHexString(s[i]).length() == 1){
sb.append("0" + Integer.toHexString(s[i]) + " ");
}else {
sb.append(Integer.toHexString(s[i]) + " ");
}
}
return sb.toString().toUpperCase();
}
public static String encodeCommonAddress(int address) {
byte[] buffer = new byte[2];
buffer[0] = (byte) address;
buffer[1] = (byte) (address >> 8);
int[] s = new int[4];
StringBuffer sb = new StringBuffer();
for (int i = 0; i < buffer.length; i++){
s[i] = (buffer[i] & 0xff);
if (Integer.toHexString(s[i]).length() == 1){
sb.append("0" + Integer.toHexString(s[i]) + " ");
}else {
sb.append(Integer.toHexString(s[i]) + " ");
}
}
return sb.toString().toUpperCase();
}
public static String encode(int num) {
byte[] buffer = new byte[2];
buffer[0] = (byte) num;
buffer[1] = (byte) (num >> 8);
int[] s = new int[4];
StringBuffer sb = new StringBuffer();
for (int i = 0; i < buffer.length; i++){
s[i] = (buffer[i] & 0xff);
if (Integer.toHexString(s[i]).length() == 1){
sb.append("0" + Integer.toHexString(s[i]) + " ");
}else {
sb.append(Integer.toHexString(s[i]) + " ");
}
}
return sb.toString().toUpperCase();
}
public static byte[] float2byte(float f) {
// 把float转换为byte[]
int fbit = Float.floatToIntBits(f);
byte[] b = new byte[4];
for (int i = 0; i < 4; i++) {
b[i] = (byte) (fbit >> (24 - i * 8));
}
// 翻转数组
int len = b.length;
// 建立一个与源数组元素类型相同的数组
byte[] dest = new byte[len];
// 为了防止修改源数组,将源数组拷贝一份副本
System.arraycopy(b, 0, dest, 0, len);
byte temp;
// 将顺位第i个与倒数第i个交换
for (int i = 0; i < len / 2; ++i) {
temp = dest[i];
dest[i] = dest[len - i - 1];
dest[len - i - 1] = temp;
}
return dest;
}
}
package com.yeejoin.amos.iec104.tcp.utils;
public class Constant {
//public static long Z_Z_PREIOD = 60 * 15;
public static long Z_Z_PREIOD = 60 * 15;
public static long Z_Z_INITIALDELAY = 0;
public static long S_S_PREIOD = 5;
}
package com.yeejoin.amos.iec104.tcp.utils;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Properties;
/**
* Created by Fuxudong on 2017-6-12.
* @Description 加载property配置文件
*/
public class FileUtils {
public static Properties loadPropFile(String filePath) throws Exception{
InputStream is = FileUtils.class.getClassLoader().getResourceAsStream(filePath);
InputStreamReader isr = new InputStreamReader(is, "GBK");
Properties properties = new Properties();
try {
properties.load(isr);
}catch (IOException ex){
ex.printStackTrace();
}finally {
is.close();
isr.close();
}
return properties;
}
public static JSONObject loadJsonFile(String filePath) throws Exception{
InputStream is = FileUtils.class.getClassLoader().getResourceAsStream(filePath);
BufferedReader br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
StringBuffer jsonStrBuff = new StringBuffer();
String brStr = null;
while ((brStr =br.readLine()) != null){
jsonStrBuff.append(brStr);
}
return JSONObject.fromObject(jsonStrBuff.toString());
}
public static JSONArray loadJsonArrayFile(String filePath) throws Exception{
InputStream is = FileUtils.class.getClassLoader().getResourceAsStream(filePath);
BufferedReader br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
StringBuffer jsonStrBuff = new StringBuffer();
String brStr = null;
while ((brStr =br.readLine()) != null){
jsonStrBuff.append(brStr);
}
return JSONArray.fromObject(jsonStrBuff.toString());
}
}
package com.yeejoin.amos.iec104.tcp.utils;
import java.util.Calendar;
import java.util.GregorianCalendar;
public class GenerateDate {
public static String getCP56Time2a() {
Calendar calendar=new GregorianCalendar();
int year = Integer.parseInt(String.valueOf(calendar.get(Calendar.YEAR)).substring(2));
int month = calendar.get(Calendar.MONTH);
int day = calendar.get(Calendar.DATE);
int hour = calendar.get(Calendar.HOUR_OF_DAY);
int minute = calendar.get(Calendar.MINUTE);
int second = calendar.get(Calendar.SECOND);
int milliSecond = calendar.get(Calendar.MILLISECOND);
int handleS = second * 1000 + milliSecond;
String yearStr = Integer.toHexString(year);
yearStr = yearStr.length() > 1?yearStr:"0".concat(yearStr);
String monthStr = Integer.toHexString(month);
monthStr = monthStr.length() > 1?monthStr:"0".concat(monthStr);
String dayStr = Integer.toHexString(day);
dayStr = dayStr.length() > 1?dayStr:"0".concat(dayStr);
String hourStr = Integer.toHexString(hour);
hourStr = hourStr.length() > 1?hourStr:"0".concat(hourStr);
String minuteStr = Integer.toHexString(minute);
minuteStr = minuteStr.length() > 1?minuteStr:"0".concat(minuteStr);
String handleSStr = Integer.toHexString(handleS);
return handleSStr + minuteStr + hourStr + dayStr + monthStr + yearStr;
}
}
package com.yeejoin.amos.iec104.utils;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.servlet.http.HttpServletResponse;
import com.yeejoin.amos.connect.utils.ExcelColumn;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.CharUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;
import org.springframework.web.multipart.MultipartFile;
public class ExcelUtils {
private final static Logger log = LoggerFactory.getLogger(ExcelUtils.class);
private final static String EXCEL2003 = "xls";
private final static String EXCEL2007 = "xlsx";
public static <T> List<T> readExcel(String path, Class<T> cls,MultipartFile file){
String fileName = file.getOriginalFilename();
if (!fileName.matches("^.+\\.(?i)(xls)$") && !fileName.matches("^.+\\.(?i)(xlsx)$")) {
log.error("上传文件格式不正确");
}
List<T> dataList = new ArrayList<>();
Workbook workbook = null;
try {
InputStream is = file.getInputStream();
if (fileName.endsWith(EXCEL2007)) {
// FileInputStream is = new FileInputStream(new File(path));
workbook = new XSSFWorkbook(is);
}
if (fileName.endsWith(EXCEL2003)) {
// FileInputStream is = new FileInputStream(new File(path));
workbook = new HSSFWorkbook(is);
}
if (workbook != null) {
//类映射 注解 value-->bean columns
Map<String, List<Field>> classMap = new HashMap<>();
List<Field> fields = Stream.of(cls.getDeclaredFields()).collect(Collectors.toList());
fields.forEach(
field -> {
ExcelColumn annotation = field.getAnnotation(ExcelColumn.class);
if (annotation != null) {
String value = annotation.value();
if (StringUtils.isBlank(value)) {
return;//return起到的作用和continue是相同的 语法
}
if (!classMap.containsKey(value)) {
classMap.put(value, new ArrayList<>());
}
field.setAccessible(true);
classMap.get(value).add(field);
}
}
);
//索引-->columns
Map<Integer, List<Field>> reflectionMap = new HashMap<>(16);
//默认读取第一个sheet
Sheet sheet = workbook.getSheetAt(0);
boolean firstRow = true;
for (int i = sheet.getFirstRowNum(); i <= sheet.getLastRowNum(); i++) {
Row row = sheet.getRow(i);
//首行 提取注解
if (firstRow) {
for (int j = row.getFirstCellNum(); j <= row.getLastCellNum(); j++) {
Cell cell = row.getCell(j);
String cellValue = getCellValue(cell);
if (classMap.containsKey(cellValue)) {
reflectionMap.put(j, classMap.get(cellValue));
}
}
firstRow = false;
} else {
//忽略空白行
if (row == null) {
continue;
}
try {
T t = cls.newInstance();
//判断是否为空白行
boolean allBlank = true;
for (int j = row.getFirstCellNum(); j <= row.getLastCellNum(); j++) {
if (reflectionMap.containsKey(j)) {
Cell cell = row.getCell(j);
String cellValue = getCellValue(cell);
if (StringUtils.isNotBlank(cellValue)) {
allBlank = false;
}
List<Field> fieldList = reflectionMap.get(j);
fieldList.forEach(
x -> {
try {
handleField(t, cellValue, x);
} catch (Exception e) {
log.error(String.format("reflect field:%s value:%s exception!", x.getName(), cellValue), e);
}
}
);
}
}
if (!allBlank) {
dataList.add(t);
} else {
log.warn(String.format("row:%s is blank ignore!", i));
}
} catch (Exception e) {
log.error(String.format("parse row:%s exception!", i), e);
}
}
}
}
} catch (Exception e) {
log.error(String.format("parse excel exception!"), e);
} finally {
if (workbook != null) {
try {
workbook.close();
} catch (Exception e) {
log.error(String.format("parse excel exception!"), e);
}
}
}
return dataList;
}
private static <T> void handleField(T t, String value, Field field) throws Exception {
Class<?> type = field.getType();
if (type == null || type == void.class || StringUtils.isBlank(value)) {
return;
}
if (type == Object.class) {
field.set(t, value);
//数字类型
} else if (type.getSuperclass() == null || type.getSuperclass() == Number.class) {
if (type == int.class || type == Integer.class) {
field.set(t, NumberUtils.toInt(value));
} else if (type == long.class || type == Long.class) {
field.set(t, NumberUtils.toLong(value));
} else if (type == byte.class || type == Byte.class) {
field.set(t, NumberUtils.toByte(value));
} else if (type == short.class || type == Short.class) {
field.set(t, NumberUtils.toShort(value));
} else if (type == double.class || type == Double.class) {
field.set(t, NumberUtils.toDouble(value));
} else if (type == float.class || type == Float.class) {
field.set(t, NumberUtils.toFloat(value));
} else if (type == char.class || type == Character.class) {
field.set(t, CharUtils.toChar(value));
} else if (type == boolean.class) {
field.set(t, BooleanUtils.toBoolean(value));
} else if (type == BigDecimal.class) {
field.set(t, new BigDecimal(value));
}
} else if (type == Boolean.class) {
field.set(t, BooleanUtils.toBoolean(value));
} else if (type == Date.class) {
//
field.set(t, value);
} else if (type == String.class) {
field.set(t, value);
} else {
Constructor<?> constructor = type.getConstructor(String.class);
field.set(t, constructor.newInstance(value));
}
}
private static String getCellValue(Cell cell) {
if (cell == null) {
return "";
}
if (cell.getCellType() == Cell.CELL_TYPE_NUMERIC) {
if (HSSFDateUtil.isCellDateFormatted(cell)) {
return HSSFDateUtil.getJavaDate(cell.getNumericCellValue()).toString();
} else {
return new BigDecimal(cell.getNumericCellValue()).toString();
}
} else if (cell.getCellType() == Cell.CELL_TYPE_STRING) {
return StringUtils.trimToEmpty(cell.getStringCellValue());
} else if (cell.getCellType() == Cell.CELL_TYPE_FORMULA) {
return StringUtils.trimToEmpty(cell.getCellFormula());
} else if (cell.getCellType() == Cell.CELL_TYPE_BLANK) {
return "";
} else if (cell.getCellType() == Cell.CELL_TYPE_BOOLEAN) {
return String.valueOf(cell.getBooleanCellValue());
} else if (cell.getCellType() == Cell.CELL_TYPE_ERROR) {
return "ERROR";
} else {
return cell.toString().trim();
}
}
public static <T> void writeExcel(HttpServletResponse response, List<T> dataList, Class<T> cls){
Field[] fields = cls.getDeclaredFields();
List<Field> fieldList = Arrays.stream(fields)
.filter(field -> {
ExcelColumn annotation = field.getAnnotation(ExcelColumn.class);
if (annotation != null && annotation.col() > 0) {
field.setAccessible(true);
return true;
}
return false;
}).sorted(Comparator.comparing(field -> {
int col = 0;
ExcelColumn annotation = field.getAnnotation(ExcelColumn.class);
if (annotation != null) {
col = annotation.col();
}
return col;
})).collect(Collectors.toList());
Workbook wb = new XSSFWorkbook();
Sheet sheet = wb.createSheet("Sheet1");
AtomicInteger ai = new AtomicInteger();
{
Row row = sheet.createRow(ai.getAndIncrement());
AtomicInteger aj = new AtomicInteger();
//写入头部
fieldList.forEach(field -> {
ExcelColumn annotation = field.getAnnotation(ExcelColumn.class);
String columnName = "";
if (annotation != null) {
columnName = annotation.value();
}
Cell cell = row.createCell(aj.getAndIncrement());
CellStyle cellStyle = wb.createCellStyle();
cellStyle.setFillForegroundColor(IndexedColors.WHITE.getIndex());
cellStyle.setFillPattern(CellStyle.SOLID_FOREGROUND);
cellStyle.setAlignment(CellStyle.ALIGN_CENTER);
Font font = wb.createFont();
font.setBoldweight(Font.BOLDWEIGHT_NORMAL);
cellStyle.setFont(font);
cell.setCellStyle(cellStyle);
cell.setCellValue(columnName);
});
}
if (CollectionUtils.isNotEmpty(dataList)) {
dataList.forEach(t -> {
Row row1 = sheet.createRow(ai.getAndIncrement());
AtomicInteger aj = new AtomicInteger();
fieldList.forEach(field -> {
Class<?> type = field.getType();
Object value = "";
try {
value = field.get(t);
} catch (Exception e) {
e.printStackTrace();
}
Cell cell = row1.createCell(aj.getAndIncrement());
if (value != null) {
if (type == Date.class) {
cell.setCellValue(value.toString());
} else {
cell.setCellValue(value.toString());
}
cell.setCellValue(value.toString());
}
});
});
}
//冻结窗格
wb.getSheet("Sheet1").createFreezePane(0, 1, 0, 1);
//浏览器下载excel
buildExcelDocument("medol.xlsx",wb,response);
//生成excel文件
// buildExcelFile(".\\default.xlsx",wb);
}
/**
* 浏览器下载excel
* @param fileName
* @param wb
* @param response
*/
private static void buildExcelDocument(String fileName, Workbook wb,HttpServletResponse response){
try {
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
response.setHeader("Content-Disposition", "attachment;filename="+URLEncoder.encode(fileName, "utf-8"));
response.flushBuffer();
wb.write(response.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 生成excel文件
* @param path 生成excel路径
* @param wb
*/
private static void buildExcelFile(String path, Workbook wb){
File file = new File(path);
if (file.exists()) {
file.delete();
}
try {
wb.write(new FileOutputStream(file));
} catch (Exception e) {
e.printStackTrace();
}
}
}
package com.yeejoin.amos.iec104.utils;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
public class NetUtil {
/***
* true:already in using false:not using
* @param port
*/
public static boolean isLoclePortUsing(int port){
boolean flag = true;
try {
flag = isPortUsing("127.0.0.1", port);
} catch (Exception e) {
}
return flag;
}
/***
* true:already in using false:not using
* @param host
* @param port
* @throws UnknownHostException
*/
public static boolean isPortUsing(String host,int port) throws UnknownHostException{
boolean flag = false;
InetAddress theAddress = InetAddress.getByName(host);
try {
Socket socket = new Socket(theAddress,port);
flag = true;
if(!socket.isClosed()) {
socket.close();
}
} catch (IOException e) {
}
return flag;
}
}
package com.yeejoin.amos.iec104.websocket;
import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import org.springframework.stereotype.Component;
@ServerEndpoint(value = "/equipmentWebsocket")
@Component
public class EquipmentWebsocket {
//静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
private static int onlineCount = 0;
//与某个客户端的连接会话,需要通过它来给客户端发送数据
private static ConcurrentHashMap<String, Session> clients = new ConcurrentHashMap<String, Session>();
/**
* 连接建立成功调用的方法
* */
@OnOpen
public void onOpen(Session session) {
clients.put(session.getId(), session);
addOnlineCount(); //在线数加1
System.out.println("有新连接加入!当前在线人数为" + getOnlineCount());
}
/**
* 连接关闭调用的方法
*/
@OnClose
public void onClose(Session session) {
if(clients.values().contains(session)) {
clients.values().remove(session);
return;
}
subOnlineCount(); //在线数减1
System.out.println("有一连接关闭!当前在线人数为" + getOnlineCount());
}
/**
* 收到客户端消息后调用的方法
*
* @param message 客户端发送过来的消息*/
@OnMessage
public void onMessage(String message, Session session) {
System.out.println("来自客户端的注册消息:" + message);
}
@OnError
public void onError(Session session, Throwable error) {
System.out.println("发生错误");
error.printStackTrace();
}
/**
* 群发自定义消息
* */
public static void sendInfo(String message) throws IOException {
for (Session websocket : clients.values()) {
try {
websocket.getBasicRemote().sendText(message);
} catch (Exception e) {
continue;
}
}
}
public static synchronized int getOnlineCount() {
return onlineCount;
}
public static synchronized void addOnlineCount() {
EquipmentWebsocket.onlineCount++;
}
public static synchronized void subOnlineCount() {
EquipmentWebsocket.onlineCount--;
}
}
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import com.yeejoin.amos.iec104.business.entity.mybatis.RecData;
@RunWith(SpringRunner.class)
@SpringBootTest
public class Test {
@org.junit.Test
public void test() {
RecData data = new RecData();
data.setSoe(1);
data.setInformationAddress(18);
data.setServerId("1");
data.setPointCode("1-18");
// RecDataQueue.getInstance().sendState(data);
}
}
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>YeeAmosConnectRoot</artifactId>
<groupId>com.yeejoin.amos</groupId>
<version>1.0.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>YeeAmosTransmitServer</artifactId>
<dependencies>
<dependency>
<groupId>com.yeejoin.amos</groupId>
<artifactId>YeeAmosConnentCommon</artifactId>
<version>1.0.0</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>
\ No newline at end of file
package com.yeejoin.amos.transmit.business.dao;
import com.yeejoin.amos.connect.dao.BaseDao;
import com.yeejoin.amos.connect.dao.entity.TransmitMapper;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository("transmitMapperDao")
public interface TransmitMapperDao extends BaseDao<TransmitMapper, Long> {
public List<TransmitMapper> findAllByMapperTypeAndMapperId(String mapperType, Long mapperId);
}
package com.yeejoin.amos.transmit.core;
import com.yeejoin.amos.transmit.tcp.TcpQueue;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Component("rpcServer")
@Scope("singleton")
public class RpcService {
public RpcService() {
TcpQueue.getInstance().start();
}
}
package com.yeejoin.amos.transmit.http;
public class HttpQueue {
}
package com.yeejoin.amos.transmit.tcp;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import java.net.InetSocketAddress;
@ChannelHandler.Sharable
public class EchoServerHandler extends SimpleChannelInboundHandler<String> {
private static final String TAG = "EchoServerHandler";
private RpcServerListener mListener;
public EchoServerHandler(RpcServerListener listener) {
this.mListener = listener;
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
cause.printStackTrace(); //5
ctx.close();
}
@Override
protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
System.out.println(new String(msg));
InetSocketAddress insocket = (InetSocketAddress) ctx.channel().remoteAddress();
String ip = insocket.getAddress().getHostAddress();
mListener.onMessageResponseServer(msg, ip);
}
/**
* 连接成功
*
* @param ctx
* @throws Exception
*/
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
mListener.onChannelConnect(ctx.channel());
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
mListener.onChannelDisConnect(ctx.channel());
}
}
package com.yeejoin.amos.transmit.tcp;
public interface RpcRecvListener {
public void recv(byte[] b);
}
package com.yeejoin.amos.transmit.tcp;
import io.netty.channel.Channel;
public interface RpcServerListener<T> {
public final static byte STATUS_CONNECT_SUCCESS = 1;
public final static byte STATUS_CONNECT_CLOSED = 0;
public final static byte STATUS_CONNECT_ERROR = 0;
/**
*
* @param msg
* @param ChannelId unique id
*/
void onMessageResponseServer(T msg,String ChannelId);
/**
* server开启成功
*/
void onStartServer();
/**
* server关闭
*/
void onStopServer();
/**
* 与客户端建立连接
*
* @param channel
*/
void onChannelConnect(Channel channel);
/**
* 与客户端断开连接
* @param
*/
void onChannelDisConnect(Channel channel);
}
package com.yeejoin.amos.transmit.tcp;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.util.CharsetUtil;
public class RpcTcpServer {
private static final String TAG = "NettyTcpServer";
private final int port = 8888;
private Channel channel;
private static RpcTcpServer instance = null;
private RpcServerListener listener;
// private boolean connectStatus;
private EventLoopGroup bossGroup;
private EventLoopGroup workerGroup;
private boolean isServerStart;
public static RpcTcpServer getInstance() {
if (instance == null) {
synchronized (RpcTcpServer.class) {
if (instance == null) {
instance = new RpcTcpServer();
}
}
}
return instance;
}
private RpcTcpServer() {
}
public void start() {
new Thread() {
@Override
public void run() {
super.run();
bossGroup = new NioEventLoopGroup(1);
workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class) // 5
// .localAddress(new InetSocketAddress(port)) // 6
.option(ChannelOption.SO_BACKLOG, 128)
// 设置连接超时时间30秒
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 30000)
.childOption(ChannelOption.SO_KEEPALIVE, true)
.childHandler(new ChannelInitializer<SocketChannel>() { // 7
@Override
public void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new StringEncoder(CharsetUtil.UTF_8));
// ch.pipeline().addLast(new LineBasedFrameDecoder(1024));
ch.pipeline().addLast(new StringDecoder(CharsetUtil.UTF_8));
ch.pipeline().addLast(new EchoServerHandler(listener));
}
});
// Bind and start to accept incoming connections.
ChannelFuture f = b.bind(port).sync(); // 8
isServerStart = true;
listener.onStartServer();
// Wait until the server socket is closed.
// In this example, this does not happen, but you can do that to gracefully
// shut down your server.
f.channel().closeFuture().sync(); // 9
} catch (Exception e) {
e.printStackTrace();
} finally {
isServerStart = false;
listener.onStopServer();
workerGroup.shutdownGracefully();
bossGroup.shutdownGracefully();
}
}
}.start();
}
public void disconnect() {
workerGroup.shutdownGracefully();
bossGroup.shutdownGracefully();
}
public void setListener(RpcServerListener listener) {
this.listener = listener;
}
// public void setConnectStatus(boolean connectStatus) {
// this.connectStatus = connectStatus;
// }
//
// public boolean getConnectStatus() {
// return connectStatus;
// }
public boolean isServerStart() {
return isServerStart;
}
// 异步发送消息
public boolean sendMsgToServer(String data, ChannelFutureListener listener) {
boolean flag = channel != null && channel.isActive();
if (flag) {
channel.writeAndFlush(data + System.getProperty("line.separator")).addListener(listener);
}
return flag;
}
// 同步发送消息
public boolean sendMsgToServer(String data) {
boolean flag = channel != null && channel.isActive();
if (flag) {
// ByteBuf buf = Unpooled.copiedBuffer(data);
// ByteBuf byteBuf = Unpooled.copiedBuffer(data + System.getProperty("line.separator"), //2
// CharsetUtil.UTF_8);
ChannelFuture channelFuture = channel.writeAndFlush(data + System.getProperty("line.separator")).awaitUninterruptibly();
return channelFuture.isSuccess();
}
return false;
}
public boolean sendMsgToServer(byte[] data, ChannelFutureListener listener) {
boolean flag = channel != null && channel.isActive();
if (flag) {
ByteBuf buf = Unpooled.copiedBuffer(data);
channel.writeAndFlush(buf).addListener(listener);
}
return flag;
}
/**
* 切换通道
* 设置服务端,与哪个客户端通信
* @param channel
*/
public void selectorChannel(Channel channel) {
this.channel = channel;
}
}
package com.yeejoin.amos.transmit.tcp;
import io.netty.channel.Channel;
import org.apache.log4j.Logger;
import java.net.InetSocketAddress;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ScheduledExecutorService;
public class TcpQueue implements RpcServerListener<String>{
ScheduledExecutorService service_send = null;
ScheduledExecutorService service_recv = null;
private volatile static TcpQueue instance = null;
private static final BlockingQueue<TcpTransmitParam> sendQueue = new LinkedBlockingQueue<TcpTransmitParam>();
private static final BlockingQueue<TcpTransmitParam> recvQueue = new LinkedBlockingQueue<TcpTransmitParam>();
private static final ConcurrentHashMap<String, Channel> mapping = new ConcurrentHashMap<>();
private static final ConcurrentHashMap<String, RpcRecvListener> recvListeners = new ConcurrentHashMap<>();
private TcpQueue() {
RpcTcpServer rpc = RpcTcpServer.getInstance();
rpc.setListener(this);
rpc.start();
}
public static TcpQueue getInstance(){
//先检查实例是否存在,如果不存在才进入下面的同步块
if(instance == null){
//同步块,线程安全的创建实例
synchronized(TcpQueue.class){
//再次检查实例是否存在,如果不存在才真的创建实例
if(instance == null){
instance = new TcpQueue();
}
}
}
return instance;
}
public void addSendData(TcpTransmitParam b) {
sendQueue.add(b);
}
public void addRecvData(TcpTransmitParam b){
recvQueue.add(b);
}
public void register(String ip, RpcRecvListener listener) {
recvListeners.put(ip, listener);
}
public void unRegister(RpcRecvListener listener) {
for (String key: recvListeners.keySet()) {
RpcRecvListener l = recvListeners.get(key);
if (listener.equals(l)) {
recvListeners.remove(key);
}
}
}
public void start() {
service_send = Executors.newSingleThreadScheduledExecutor();
service_send.execute(send_runnable);
service_recv = Executors.newSingleThreadScheduledExecutor();
service_recv.execute(recv_runnable);
}
Runnable send_runnable = new Runnable() {
public void run() {
while(true) {
try {
TcpTransmitParam data = sendQueue.take();
System.out.println(new String(data.getData()));
for (String key: recvListeners.keySet()) {
RpcRecvListener l = recvListeners.get(key);
if (key.equals(data.getIp())) {
l.recv(data.getData());
}
}
} catch (Exception e) {
Logger.getLogger(this.getClass()).error(e.getMessage());
e.printStackTrace();
}
}
}
};
Runnable recv_runnable = new Runnable() {
public void run() {
while(true) {
try {
TcpTransmitParam data = recvQueue.take();
System.out.println(new String(data.getData()));
for (String key: mapping.keySet()) {
Channel channel = mapping.get(key);
InetSocketAddress insocket = (InetSocketAddress) channel.remoteAddress();
String ip = insocket.getAddress().getHostAddress();
if (ip.equals(data.getIp())) {
channel.writeAndFlush(new String(data.getData()));
}
}
} catch (Exception e) {
Logger.getLogger(this.getClass()).error(e.getMessage());
e.printStackTrace();
}
}
}
};
@Override
public void onMessageResponseServer(String msg, String ip) {
Channel channel = mapping.get(ip);
TcpTransmitParam data = new TcpTransmitParam();
data.setData(msg.getBytes());
data.setIp(ip);
this.addSendData(data);
}
@Override
public void onStartServer() {
}
@Override
public void onStopServer() {
mapping.clear();
}
@Override
public void onChannelConnect(Channel channel) {
InetSocketAddress insocket = (InetSocketAddress) channel.remoteAddress();
String ip = insocket.getAddress().getHostAddress();
mapping.put(ip, channel);
}
@Override
public void onChannelDisConnect(Channel channel) {
InetSocketAddress insocket = (InetSocketAddress) channel.remoteAddress();
String ip = insocket.getAddress().getHostAddress();
mapping.remove(ip);
}
}
package com.yeejoin.amos.transmit.tcp;
public class TcpTransmitParam {
private String ip;
private byte[] data;
public String getIp() {
return ip;
}
public byte[] getData() {
return data;
}
public void setIp(String ip) {
this.ip = ip;
}
public void setData(byte[] data) {
this.data = data;
}
}
package com.yeejoin.amos.transmit.udp;
public class UdpQueue {
}
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>YeeAmosIec104IntfRoot</artifactId>
<groupId>com.yeejoin.amos</groupId>
<version>1.0.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>YeeAmosUartServer</artifactId>
<dependencies>
<!-- 安全模块jar -->
<dependency>
<groupId>com.yeejoin.amos</groupId>
<artifactId>AmosOPService</artifactId>
<version>${YeeOp.version}</version>
</dependency>
<dependency>
<groupId>com.yeejoin.amos</groupId>
<artifactId>YeeAmosConnentCommon</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>com.yeejoin.amos</groupId>
<artifactId>YeeAmosTransmitServer</artifactId>
<version>1.0.0</version>
</dependency>
<!--串口通信依赖-->
<dependency>
<groupId>org.bidib.jbidib.org.qbang.rxtx</groupId>
<artifactId>rxtxcomm</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>com.yeejoin.amos</groupId>
<artifactId>amos-authtoken</artifactId>
<version>${YeeSecurity.version}</version>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.github.oshi</groupId>
<artifactId>oshi-core</artifactId>
<version>3.5.0</version>
</dependency>
</dependencies>
</project>
\ No newline at end of file
package com.yeejoin.amos.uart.business.controller;
import com.yeejoin.amos.connect.dao.entity.UartVo;
import com.yeejoin.amos.op.core.common.response.CommonResponse;
import com.yeejoin.amos.op.core.util.CommonResponseUtil;
import com.yeejoin.amos.security.authorization.Authorization;
import com.yeejoin.amos.uart.business.param.UartParam;
import com.yeejoin.amos.uart.business.service.intfc.UartService;
import io.swagger.annotations.Api;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.io.InputStream;
@RestController
@RequestMapping(value = "/uart")
@Api(tags = "串口api")
public class UartController {
@Autowired
private UartService uartService;
public CommonResponse createUart(UartVo uart) {
return null;
}
public CommonResponse deleteUart(Long[] ids) {
return null;
}
public CommonResponse findUartById(Long id) {
return null;
}
public CommonResponse findAll() {
return null;
}
public CommonResponse findSystemSerialPort() {
return null;
}
@PostMapping(value = "/sendData", produces = "application/json;charset=UTF-8")
@Authorization(ingore = true)
public CommonResponse sendData(@RequestBody UartParam param) {
uartService.sendData(param.getComPort(), param.getMessage());
return CommonResponseUtil.success();
}
@PostMapping(value = "/sendFile", produces = "application/json;charset=UTF-8")
@Authorization(ingore = true)
public CommonResponse sendFile(@RequestParam(value="file", required = false) MultipartFile file, @RequestParam("serialPort") String serialPort) {
if (ObjectUtils.isEmpty(file)) {
return CommonResponseUtil.failure("文件不可以为空");
}
if (ObjectUtils.isEmpty("serialPort")) {
return CommonResponseUtil.failure("串口不可以为空");
}
InputStream is = null;
try {
is = file.getInputStream();
int iAvail = is.available();
byte[] bytes = new byte[iAvail];
is.read(bytes);
uartService.sendBytes(serialPort, bytes);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return CommonResponseUtil.success();
}
}
package com.yeejoin.amos.uart.business.dao;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.NoRepositoryBean;
import org.springframework.data.repository.PagingAndSortingRepository;
import java.io.Serializable;
import java.util.List;
/**
* 基础dao
*
* @param <T>
* @param <ID>
*/
@NoRepositoryBean
public interface BaseDao<T, ID extends Serializable> extends JpaRepository<T, ID>, CrudRepository<T, ID>,
PagingAndSortingRepository<T, ID>, JpaSpecificationExecutor<T> {
public default T getOneBySpecification(Specification<T> specification) {
List<T> list = findAll(specification);
if (list.isEmpty()) {
return null;
} else {
return list.get(0);
}
}
}
package com.yeejoin.amos.uart.business.dao;
import com.yeejoin.amos.connect.dao.entity.UartVo;
import org.springframework.stereotype.Repository;
@Repository("uartDao")
public interface UartDao extends BaseDao<UartVo, Long>{
}
package com.yeejoin.amos.uart.business.param;
public class UartParam {
String comPort;
String message;
public String getComPort() {
return comPort;
}
public String getMessage() {
return message;
}
public void setComPort(String comPort) {
this.comPort = comPort;
}
public void setMessage(String message) {
this.message = message;
}
}
package com.yeejoin.amos.uart.business.service.impl;
import com.yeejoin.amos.connect.dao.entity.TransmitMapper;
import com.yeejoin.amos.connect.dao.entity.UartVo;
import com.yeejoin.amos.transmit.business.dao.TransmitMapperDao;
import com.yeejoin.amos.transmit.tcp.RpcRecvListener;
import com.yeejoin.amos.transmit.tcp.TcpQueue;
import com.yeejoin.amos.transmit.tcp.TcpTransmitParam;
import com.yeejoin.amos.uart.business.dao.UartDao;
import com.yeejoin.amos.uart.business.service.intfc.UartService;
import com.yeejoin.amos.uart.rxtx.DefaultSerialDataListener;
import com.yeejoin.amos.uart.rxtx.SerialContext;
import com.yeejoin.amos.uart.rxtx.SerialUtils;
import com.yeejoin.amos.uart.rxtx.parse.HexStringSerialDataParser;
import com.yeejoin.amos.uart.rxtx.processor.SerialByteDataProcessor;
import com.yeejoin.amos.uart.rxtx.reader.AnyDataReader;
import gnu.io.CommPortIdentifier;
import gnu.io.SerialPort;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
@Service("uartService")
public class UartServiceImpl implements UartService {
@Resource
UartDao uartDao;
@Resource
private TransmitMapperDao transmitMapperDao;
private static ScheduledExecutorService initUartService = null;
private static HashSet<UartVo> notInitUart = new HashSet<UartVo>();
public UartServiceImpl() {
initUartService = Executors.newSingleThreadScheduledExecutor();
initUartService.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
Iterator<UartVo> iterator = notInitUart.iterator();
while (iterator.hasNext()) {
UartVo uart = iterator.next();
List<TransmitMapper> tmList = transmitMapperDao.findAllByMapperTypeAndMapperId("UART", uart.getId());
SerialPort connect = null;
try {
connect = SerialUtils.connect(uart.getSerialPort(), uart.getBaudRate());
} catch (Exception e) {
e.printStackTrace();
continue;
}
SerialContext serialContext = SerialContext.build(connect);
serialContext.setSerialReader(new AnyDataReader(serialContext));
serialContext.getSerialDataParserSet().add(new HexStringSerialDataParser());
serialContext.setSerialPortEventListener(new DefaultSerialDataListener(serialContext));
serialContext.setSerialByteDataProcessor(new SerialByteDataProcessor() {
private List<TransmitMapper> uartTMList = tmList;
@Override
public void process(byte[] bytes) {
for (TransmitMapper tm : uartTMList) {
if ("TCP".equals(tm.getTransmitType())) {
TcpTransmitParam p = new TcpTransmitParam();
p.setIp(tm.getTransmitUrl());
p.setData(bytes);
TcpQueue.getInstance().addRecvData(p);
}
}
}
});
for (TransmitMapper tm : tmList) {
if ("TCP".equals(tm.getTransmitType())) {
TcpQueue.getInstance().register(tm.getTransmitIp(), new RpcRecvListener(){
@Override
public void recv(byte[] b) {
UartVo uart = uartDao.findOne(tm.getMapperId());
sendBytes("//./"+uart.getSerialPort(), b);
}
});
}
}
iterator.remove();
}
}
}, 1, 1, TimeUnit.SECONDS);
}
@Override
public void saveUart(UartVo vo) {
}
@Override
public UartVo findById(Long id) {
return null;
}
@Override
public List<UartVo> findAll() {
return uartDao.findAll();
}
@Override
public void delete(Long ids) {
}
@Override
public void sendData(String comPort, String message) {
try {
SerialContext serialContext = SerialContext.findSerialContextBySerialPort("//./"+comPort);
if (ObjectUtils.isEmpty(serialContext)) {
return;
}
serialContext.sendData(message.getBytes());
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void sendBytes(String serialPort, byte[] bytes) {
try {
SerialContext serialContext = SerialContext.findSerialContextBySerialPort("//./"+serialPort);
if (ObjectUtils.isEmpty(serialContext)) {
return;
}
serialContext.sendData(bytes);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public List<String> findAllSystemSerialPort() {
Enumeration<CommPortIdentifier> portList = CommPortIdentifier.getPortIdentifiers();//获得所有串口
ArrayList<String> portNameList = new ArrayList<>();
//串口名字添加到List并返回
while (portList.hasMoreElements()) {
String portName = portList.nextElement().getName();
portNameList.add(portName);
}
return portNameList;
}
@PostConstruct
public void initSerial() {
List<UartVo> list = findAll();
for(UartVo uart : list) {
List<TransmitMapper> tmList = transmitMapperDao.findAllByMapperTypeAndMapperId("UART", uart.getId());
SerialPort connect = null;
List<String> commNames = SerialUtils.getCommNames();
if (!commNames.contains(uart.getSerialPort())) {
notInitUart.add(uart);
}
try {
connect = SerialUtils.connect(uart.getSerialPort(), uart.getBaudRate());
} catch (Exception e) {
e.printStackTrace();
notInitUart.add(uart);
continue;
}
SerialContext serialContext = SerialContext.build(connect);
serialContext.setSerialReader(new AnyDataReader(serialContext));
serialContext.getSerialDataParserSet().add(new HexStringSerialDataParser());
serialContext.setSerialPortEventListener(new DefaultSerialDataListener(serialContext));
serialContext.setSerialByteDataProcessor(new SerialByteDataProcessor() {
private List<TransmitMapper> uartTMList = tmList;
@Override
public void process(byte[] bytes) {
for (TransmitMapper tm : uartTMList) {
if ("TCP".equals(tm.getTransmitType())) {
TcpTransmitParam p = new TcpTransmitParam();
p.setIp(tm.getTransmitUrl());
p.setData(bytes);
TcpQueue.getInstance().addRecvData(p);
}
}
}
});
for (TransmitMapper tm : tmList) {
if ("TCP".equals(tm.getTransmitType())) {
TcpQueue.getInstance().register(tm.getTransmitIp(), new RpcRecvListener(){
@Override
public void recv(byte[] b) {
UartVo uart = uartDao.findOne(tm.getMapperId());
sendBytes("//./"+uart.getSerialPort(), b);
}
});
}
}
}
}
}
package com.yeejoin.amos.uart.business.service.intfc;
import com.yeejoin.amos.connect.dao.entity.UartVo;
import java.util.List;
/**
* 串口服务接口
*/
public interface UartService {
/**
* 保存串口配置
* @param vo
*/
public void saveUart(UartVo vo);
/**
* 通过Id查询串口信息
* @param id
* @return
*/
public UartVo findById(Long id);
/**
* 查询所有串口信息
* @return
*/
public List<UartVo> findAll();
/**
* 查询串口
* @param ids
*/
public void delete(Long ids);
/**
* 给指定串口发送数据
* @param comPort
* @param message
*/
public void sendData(String comPort, String message);
/**
* 获取操作系统所有的串口
* @return
*/
public List<String> findAllSystemSerialPort();
/**
* 传输文件
* @param serialPort
* @param bytes
*/
void sendBytes(String serialPort, byte[] bytes);
}
package com.yeejoin.amos.uart.rxtx;
import com.yeejoin.amos.uart.rxtx.parse.SerialDataParser;
import com.yeejoin.amos.uart.rxtx.processor.SerialByteDataProcessor;
import com.yeejoin.amos.uart.rxtx.processor.SerialDataProcessor;
import gnu.io.SerialPortEvent;
import gnu.io.SerialPortEventListener;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Set;
public class DefaultSerialDataListener implements SerialPortEventListener {
private SerialContext serialContext;
public DefaultSerialDataListener(SerialContext serialContext) {
this.serialContext = serialContext;
}
@Override
public void serialEvent(SerialPortEvent ev) {
switch (ev.getEventType()) {
case SerialPortEvent.DATA_AVAILABLE:
Set<SerialDataParser> parserSet = serialContext.getSerialDataParserSet();
byte[] bytes = serialContext.readData();
if (bytes == null) {
return;
}
Object parse;
for (SerialDataParser serialDataParser : parserSet) {
parse = serialDataParser.parse(bytes);
if (parse != null) {
dataProcessors(parse);
}
}
if (bytes.length > 0) {
SerialByteDataProcessor processor = serialContext.getSerialByteDataProcessor();
if (processor != null) {
processor.process(bytes);
}
}
break;
case SerialPortEvent.BI: // 10 通讯中断
System.err.println("与串口设备通讯中断");
break;
default:
System.err.println("data parse err or not find parser");
}
}
private void dataProcessors(Object obj) {
Set<SerialDataProcessor> dataProcessors = serialContext.getSerialDataProcessorSet();
for (SerialDataProcessor serialDataProcessor : dataProcessors) {
Class cl = serialDataProcessor.getClass();
Class c2 = cl.getSuperclass();
while (!c2.equals(Object.class)) {
cl = cl.getSuperclass();
c2 = cl.getSuperclass();
}
Type[] types = cl.getGenericInterfaces();
for (Type type : types) {
if (type instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) type;
Type rawType = parameterizedType.getRawType();
if (rawType instanceof Class) {
boolean equals = rawType.equals(SerialDataProcessor.class);
if (equals) {
String typeName = ((ParameterizedType) type).getActualTypeArguments()[0].getTypeName();
try {
Class<?> forName = Class.forName(typeName);
if (forName == obj.getClass()) {
serialDataProcessor.process(obj);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
}
}
}
}
}
package com.yeejoin.amos.uart.rxtx;
/**
* @author han xinjian
**/
public class HexUtil {
public static byte[] HexStringToBytes(String str) {
if (str == null || str.length() <= 0) {
return new byte[0];
}
str = str.trim();
str = str.replaceAll("ox", "");
str = str.replaceAll(" ", "");
str = str.replaceAll("oX", "");
str = str.replaceAll(",", "");
byte[] bytes = new byte[str.length() / 2];
for (int i = 0; i < str.length() / 2; i++) {
String subStr = str.substring(i * 2, i * 2 + 2);
bytes[i] = (byte) Integer.parseInt(subStr, 16);
}
return bytes;
}
public static String bytesToHexString(byte[] src) {
StringBuilder stringBuilder = new StringBuilder();
if (src == null || src.length <= 0) {
return null;
}
for (byte b : src) {
int v = b & 0xFF;
String hv = Integer.toHexString(v);
if (hv.length() < 2) {
stringBuilder.append(0);
}
stringBuilder.append(hv);
stringBuilder.append(" ");
}
return stringBuilder.toString();
}
}
package com.yeejoin.amos.uart.rxtx;
import java.util.Properties;
public class OSUtil {
private static String osName;
private static String arch;
static {
Properties props = System.getProperties();
osName = props.getProperty("os.name");
arch = props.getProperty("os.arch");
System.out.println("osName: " + osName);
System.out.println("arch: " + arch);
}
public static String getOsName() {
return osName;
}
public static String getArch() {
return arch;
}
}
package com.yeejoin.amos.uart.rxtx;
import com.yeejoin.amos.uart.rxtx.parse.SerialDataParser;
import com.yeejoin.amos.uart.rxtx.processor.SerialByteDataProcessor;
import com.yeejoin.amos.uart.rxtx.processor.SerialDataProcessor;
import com.yeejoin.amos.uart.rxtx.reader.SerialReader;
import gnu.io.RXTXPort;
import gnu.io.SerialPort;
import gnu.io.SerialPortEventListener;
import org.springframework.util.ObjectUtils;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.TooManyListenersException;
/**
* @author han xinjian
**/
public class SerialContext {
public static List<SerialContext> queue = new ArrayList<SerialContext>();
private SerialPort serialPort;
private SerialReader serialReader;
private SerialByteDataProcessor serialByteDataProcessor;
private SerialPortEventListener serialPortEventListener;
private SerialContext() {};
public static SerialContext findSerialContextBySerialPort(String serialPort) throws Exception {
if (ObjectUtils.isEmpty(serialPort)) {
throw new Exception("传入参数不可以为空");
}
for(SerialContext context: queue) {
System.out.println(context.getSerialPort().getName());
if (serialPort.equals(context.getSerialPort().getName())) {
return context;
}
}
return null;
}
public SerialContext build() {
return new SerialContext();
}
public static SerialContext build(SerialPort serialPort) {
SerialContext serialContext = new SerialContext();
serialContext.setSerialPort(serialPort);
queue.add(serialContext);
return serialContext;
}
public static SerialContext build(SerialPort serialPort, SerialByteDataProcessor serialByteDataProcessor, SerialPortEventListener serialPortEventListener) {
SerialContext serialContext = new SerialContext();
serialContext.setSerialPort(serialPort);
serialContext.setSerialByteDataProcessor(serialByteDataProcessor);
serialContext.serialPortEventListener = serialPortEventListener;
autoSerialPortAddEventListener(serialContext, serialPort);
queue.add(serialContext);
return serialContext;
}
public static SerialContext build(SerialPort serialPort, SerialPortEventListener serialPortEventListener) {
SerialContext serialContext = new SerialContext();
serialContext.setSerialPort(serialPort);
serialContext.serialPortEventListener = serialPortEventListener;
autoSerialPortAddEventListener(serialContext, serialPort);
queue.add(serialContext);
return serialContext;
}
public SerialPortEventListener getSerialPortEventListener() {
return serialPortEventListener;
}
public void setSerialPortEventListener(SerialPortEventListener serialPortEventListener) {
this.serialPortEventListener = serialPortEventListener;
autoSerialPortAddEventListener(this, serialPort);
}
private static void autoSerialPortAddEventListener(SerialContext serialContext, SerialPort serialPort) {
if (serialContext.serialPortEventListener != null && serialPort != null) {
serialPort.removeEventListener();
try {
serialPort.addEventListener(serialContext.serialPortEventListener);
serialPort.notifyOnDataAvailable(true);
} catch (TooManyListenersException e) {
e.printStackTrace();
}
}
}
public SerialReader getSerialReader() {
return serialReader;
}
public SerialByteDataProcessor getSerialByteDataProcessor() {
return serialByteDataProcessor;
}
public void setSerialByteDataProcessor(SerialByteDataProcessor serialByteDataProcessor) {
this.serialByteDataProcessor = serialByteDataProcessor;
}
public void setSerialDataParserSet(Set<SerialDataParser> serialDataParserSet) {
this.serialDataParserSet = serialDataParserSet;
}
public void setSerialDataProcessorSet(Set<SerialDataProcessor> serialDataProcessorSet) {
this.serialDataProcessorSet = serialDataProcessorSet;
}
private Set<SerialDataParser> serialDataParserSet =
Collections.synchronizedSet(new HashSet<SerialDataParser>());
public Set<SerialDataProcessor> serialDataProcessorSet =
Collections.synchronizedSet(new HashSet<SerialDataProcessor>());
public Set<SerialDataProcessor> getSerialDataProcessorSet() {
return serialDataProcessorSet;
}
public Set<SerialDataParser> getSerialDataParserSet() {
return serialDataParserSet;
}
public void setSerialReader(SerialReader serialReader) {
this.serialReader = serialReader;
}
public void setSerialPort(SerialPort serialPort) {
this.serialPort = serialPort;
autoSerialPortAddEventListener(this, serialPort);
}
public final int DEFAULT_OUT_TIME = 100;
public byte[] sendAndRead(byte[] data) {
return sendAndRead(data, DEFAULT_OUT_TIME);
}
public <T> T sendAndRead(byte[] data, SerialDataParser<T> parser) {
byte[] bytes = sendAndRead(data);
return parser.parse(bytes);
}
public byte[] sendAndRead(byte[] data, int outTime) {
serialPort.notifyOnDataAvailable(false);
sendData(data);
return readData(outTime);
}
public <T> T sendAndRead(byte[] data, int outTime, SerialDataParser<T> parser) {
byte[] bytes = sendAndRead(data, outTime);
return parser.parse(bytes);
}
public byte[] readData() {
return readData(DEFAULT_OUT_TIME);
}
public byte[] readData(int outTime) {
serialPort.notifyOnDataAvailable(false);
while (outTime-- > 0) {
byte[] bytes = serialReader.readBytes();
if (bytes != null && bytes.length > 0) {
serialPort.notifyOnDataAvailable(true);
return bytes;
}
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
serialPort.notifyOnDataAvailable(true);
return null;
}
public boolean sendData(byte[] data) {
try {
if (data.length < 4094) {
byte[] sendbytes = new byte[data.length + 2];
sendbytes[0] = 0x00;
System.arraycopy(data,0, sendbytes, 1, data.length);
sendbytes[data.length + 1] = (byte) 0xff;
serialPort.getOutputStream().write(sendbytes);
} else {
int need = data.length / 1024;
if (data.length % 1024 > 0) {
need++;
}
for (int index = 0; index < need; index++) {
if (index == 0) {
byte[] sendbytes = new byte[1025];
sendbytes[0] = 0x00;
System.arraycopy(data,0, sendbytes, 1, 1024);
serialPort.getOutputStream().write(sendbytes);
}else if (index == need -1) {
byte[] sendbytes = new byte[data.length % 1024 + 1];
System.arraycopy(data,data.length - data.length % 1024, sendbytes, 0, data.length % 1024);
sendbytes[data.length % 1024] = (byte) 0xfe;
serialPort.getOutputStream().write(sendbytes);
} else {
byte[] sendbytes = new byte[1024];
System.arraycopy(data,1024 * index, sendbytes, 0, 1024);
serialPort.getOutputStream().write(sendbytes);
}
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
// os.write(data);
// serialPort.getOutputStream().write(data);
return true;
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
public boolean sendData(SerialSendDataEntity obj) {
return sendData(obj.getBytes());
}
public SerialPort getSerialPort() {
return serialPort;
}
}
package com.yeejoin.amos.uart.rxtx;
/**
* @author han xinjian
**/
@FunctionalInterface
public interface SerialSendDataEntity {
/**
* 数据的反解析接口
*
* @return data
*/
byte[] getBytes();
}
package com.yeejoin.amos.uart.rxtx;
import gnu.io.CommPort;
import gnu.io.CommPortIdentifier;
import gnu.io.NoSuchPortException;
import gnu.io.RXTXVersion;
import gnu.io.SerialPort;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ScheduledExecutorService;
public class SerialUtils {
/**
* 添加串口GUN.IO动态库
*/
public static void initJavaLibraryPath() {
String os = OSUtil.getOsName().split(" ")[0];
String arch = OSUtil.getArch();
Resource resource = new ClassPathResource("lib");
try {
String path = resource.getFile().getPath();
path = path + File.separator + os + File.separator;
if (os.contains("Linux") && arch.contains("86")) {
path += "i686-unknown-linux-gnu";
} else if (os.contains("Linux") && arch.contains("64")) {
path += "x86_64-unknown-linux-gnu";
}
System.out.println(path);
addLibraryDir(path);
} catch (IOException e) {
e.printStackTrace();
}
}
public static void addLibraryDir(String libraryPath) throws IOException {
try {
Field field = ClassLoader.class.getDeclaredField("usr_paths");
field.setAccessible(true);
String[] paths = (String[]) field.get(null);
for (int i = 0; i < paths.length; i++) {
if (libraryPath.equals(paths[i])) {
return;
}
}
String[] tmp = new String[paths.length + 1];
System.arraycopy(paths, 0, tmp, 0, paths.length);
tmp[paths.length] = libraryPath;
field.set(null, tmp);
} catch (IllegalAccessException e) {
throw new IOException(
"Failedto get permissions to set library path");
} catch (NoSuchFieldException e) {
throw new IOException(
"Failedto get field handle to set library path");
}
}
/**
* get all port list
*
* @return port list
*/
public static ArrayList<String> getCommNames() {
@SuppressWarnings("portIdentifiers")
Enumeration<CommPortIdentifier> portIdentifiers = CommPortIdentifier.getPortIdentifiers();
ArrayList<String> list = new ArrayList<String>();
while (portIdentifiers.hasMoreElements()) {
list.add(portIdentifiers.nextElement().getName());
}
return list.isEmpty() ? null : list;
}
/**
* connect SerialPort
*
* start --- data --- parity --- stop
* 1 5~9 0-1 1-2
* @param portName portName com口
* @param baudRate baudRate 波特率
* @param dataBits dataBits 数据占用位数
* @param stopBits stopBits 停止位
* @param parity parity 奇偶校验位
* @return SerialPort
* @throws Exception SerialPort connect err
*/
public static SerialPort connect(String portName, int baudRate, int dataBits, int stopBits, int parity) throws Exception {
System.out.println(portName + " " + baudRate + " " + dataBits + " " + stopBits + " " + parity);
CommPortIdentifier portIdentifier = null;
portIdentifier = CommPortIdentifier.getPortIdentifier(portName);
if (portIdentifier.isCurrentlyOwned()) {
System.err.println("Error: Port is currently in use");
} else {
CommPort commPort = portIdentifier.open(SerialUtils.class.getName(), 2000);
if (commPort instanceof SerialPort) {
SerialPort serialPort = (SerialPort) commPort;
serialPort.setOutputBufferSize(40960);
serialPort.setInputBufferSize(40960);
serialPort.setSerialPortParams(baudRate, dataBits, stopBits, parity);
return (SerialPort) commPort;
} else {
System.err.println("Error: Only serial ports are handled by this example.");
}
}
return null;
}
/**
* connect SerialPort
*
* @param portName port name
* @param baudRate baudRate
* @return SerialPort
* @throws Exception SerialPort connect err
*/
public static SerialPort connect(String portName, int baudRate) throws Exception {
CommPortIdentifier portIdentifier = null;
portIdentifier = CommPortIdentifier.getPortIdentifier(portName);
if (portIdentifier.isCurrentlyOwned()) {
System.err.println("Error: Port is currently in use");
} else {
CommPort commPort = portIdentifier.open(SerialUtils.class.getName(), 2000);
CommPortIdentifier.getPortIdentifiers();
if (commPort instanceof SerialPort) {
SerialPort serialPort = (SerialPort) commPort;
serialPort.setOutputBufferSize(40960);
serialPort.setInputBufferSize(40960);
serialPort.setSerialPortParams(baudRate, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
return (SerialPort) commPort;
} else {
System.err.println("Error: Only serial ports are handled by this example.");
}
}
return null;
}
}
package com.yeejoin.amos.uart.rxtx.parse;
import com.yeejoin.amos.uart.rxtx.HexUtil;
/**
* @author han xinjian
**/
public class HexStringSerialDataParser implements SerialDataParser<String> {
@Override
public String parse(byte[] bytes) {
return HexUtil.bytesToHexString(bytes);
}
}
package com.yeejoin.amos.uart.rxtx.parse;
/**
* @author han xinjian
**/
@FunctionalInterface
public interface SerialDataParser<T> {
/**
*
* Convert To Data Based On Data
*
* @param bytes data
* @return object
*/
T parse(byte[] bytes);
}
package com.yeejoin.amos.uart.rxtx.parse;
/**
* @author han xinjian
**/
public class StringSerialDataParser implements SerialDataParser<String> {
@Override
public String parse(byte[] bytes) {
return new String(bytes);
}
}
package com.yeejoin.amos.uart.rxtx.processor;
/**
* @author han xinjian
**/
@FunctionalInterface
public interface SerialByteDataProcessor {
/**
* 处理接收的元字节数据
*
* @param bytes data
*/
void process(byte[] bytes);
}
package com.yeejoin.amos.uart.rxtx.processor;
/**
* @author han xinjian
**/
@FunctionalInterface
public interface SerialDataProcessor<T> {
/**
* 处理接收到的信息
*
* @param t object
*/
void process(T t);
}
package com.yeejoin.amos.uart.rxtx.reader;
import com.yeejoin.amos.uart.rxtx.SerialContext;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Arrays;
/**
* @author han xinjian
**/
public class AnyDataReader implements SerialReader {
SerialContext serialContext;
public AnyDataReader(SerialContext serialContext) {
this.serialContext = serialContext;
}
@Override
public byte[] readBytes() {
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
try {
int read = serialContext.getSerialPort().getInputStream().read();
while (read != -1) {
byteBuffer.put(((byte) read));
read = serialContext.getSerialPort().getInputStream().read();
}
return Arrays.copyOf(byteBuffer.array(), byteBuffer.position());
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
package com.yeejoin.amos.uart.rxtx.reader;
import com.yeejoin.amos.uart.rxtx.SerialContext;
import java.io.IOException;
/**
* @author han xinjian
**/
public class ConstLengthSerialReader implements SerialReader {
private int length;
private int index = 0;
private byte[] bytes;
private boolean read = true;
SerialContext serialContext;
public ConstLengthSerialReader(SerialContext serialContext) {
this.serialContext = serialContext;
}
@Override
public byte[] readBytes() {
for (; index < length; index++) {
try {
int read = this.serialContext.getSerialPort().getInputStream().read();
if (read == -1) {
break;
} else {
bytes[index] = (byte) read;
}
} catch (IOException e) {
e.printStackTrace();
}
}
if (index == length) {
index = 0;
return bytes;
}
return null;
}
public ConstLengthSerialReader() {
length = 24;
bytes = new byte[length];
}
ConstLengthSerialReader(int length) {
this.length = length;
bytes = new byte[length];
}
}
package com.yeejoin.amos.uart.rxtx.reader;
import com.yeejoin.amos.uart.rxtx.SerialContext;
import java.nio.ByteBuffer;
import java.util.Arrays;
/**
* @author han xinjian
**/
public class LiveControlSerialReader implements SerialReader {
private byte[] startChat;
private int flagIndex;
private int dataLengthIndex;
private int allLength = 0;
private int length;
private ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
private boolean notOver = false;
SerialContext serialContext;
public LiveControlSerialReader(SerialContext serialContext, int flagIndex, int dataLengthIndex, byte... startChat) {
this.startChat = startChat;
this.flagIndex = flagIndex;
this.dataLengthIndex = dataLengthIndex;
this.serialContext = serialContext;
}
@Override
public byte[] readBytes() {
try {
byte read = ((byte) serialContext.getSerialPort().getInputStream().read());
int index = Arrays.binarySearch(startChat, read);
if (index >= 0) {
byteBuffer.put(read);
allLength = 1;
notOver = true;
} else {
if (notOver) {
if (allLength == dataLengthIndex) {
length = read;
}
allLength += 1;
byteBuffer.put(read);
if (allLength == flagIndex + length) {
notOver = false;
byte[] array = Arrays.copyOf(byteBuffer.array(), byteBuffer.position());
byteBuffer = ByteBuffer.allocate(1024);
allLength = 0;
return array;
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
package com.yeejoin.amos.uart.rxtx.reader;
/**
* @author han xinjian
**/
@FunctionalInterface
public interface SerialReader {
/**
* read a byte array
*
* @return data
*/
byte[] readBytes();
}
package com.yeejoin.amos.uart.rxtx.reader;
import com.yeejoin.amos.uart.rxtx.SerialContext;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Arrays;
/**
* @author han xinjian
**/
public class VariableLengthSerialReader implements SerialReader {
private ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
private char startChar = '{';
private char endChar = '}';
SerialContext serialContext;
public VariableLengthSerialReader(SerialContext serialContext) {
this.serialContext = serialContext;
}
public VariableLengthSerialReader(SerialContext serialContext, char startChar, char endChar) {
this.startChar = startChar;
this.endChar = endChar;
}
@Override
public byte[] readBytes() {
int ch = 0;
while (ch != -1) {
try {
ch = serialContext.getSerialPort().getInputStream().read();
if (ch == startChar) {
byteBuffer = ByteBuffer.allocate(1024);
byteBuffer.put((byte) ch);
continue;
}
if (ch == endChar) {
if (byteBuffer.position() > 0) {
if (((char) byteBuffer.get(0)) == startChar) {
byteBuffer.put((byte) ch);
byte[] array = Arrays.copyOf(byteBuffer.array(), byteBuffer.position());
byteBuffer = ByteBuffer.allocate(1024);
return array;
} else {
byteBuffer = ByteBuffer.allocate(1024);
}
}
}
byteBuffer.put((byte) ch);
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
}
Wed Mar 1 12:05:10 MST 2006
We forgot to update the Mac OS X binary. Previously, it was an old version
(RXTX-2.1-7pre20). This has now been corrected.
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.yeejoin.amos</groupId>
<artifactId>YeeAmosConnectRoot</artifactId>
<version>1.0.0</version>
<packaging>pom</packaging>
<name>YeeAmosConnectRoot</name>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.2.RELEASE</version>
</parent>
<modules>
<module>YeeAmosConnectStart</module>
<module>YeeAmosConnectCommon</module>
<module>YeeAmosIec104IntfServer</module>
<!--<module>YeeAmosUartServer</module>-->
<!--<module>YeeAmosTransmitServer</module>-->
</modules>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<sqlserver.version>6.1.0.jre8</sqlserver.version>
<swagger.version>2.7.0</swagger.version>
<spring-cloud.version>Dalston.SR5</spring-cloud.version>
<YeeSecurity.version>1.3.3</YeeSecurity.version>
<YeeOp.version>1.2.3</YeeOp.version>
<YeeLicense.version>1.0.0</YeeLicense.version>
<iec104.version>1.0.0</iec104.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
<!-- Swagger2模块 -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${swagger.version}</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${swagger.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<exclusions>
<exclusion>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-jdbc</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j</artifactId>
<version>1.3.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- 添加fastjson 依赖包. -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.15</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.0</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.6</version>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>3.7.5</version>
</dependency>
<dependency>
<groupId>com.github.jsqlparser</groupId>
<artifactId>jsqlparser</artifactId>
<version>0.9.1</version>
</dependency>
<!-- 通用Mapper -->
<dependency>
<groupId>com.github.abel533</groupId>
<artifactId>mapper</artifactId>
<version>3.0.1</version>
</dependency>
<!-- 添加commons-lang依赖包 -->
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.4</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.3.1</version>
</dependency>
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.22.Final</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-1.2-api</artifactId>
<version>2.8.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.13</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.13</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<distributionManagement>
<repository>
<id>analyse-operate-release</id>
<name>analyse-operate Porject Release</name>
<url>http://172.16.1.6:8081/nexus/content/repositories/releases/</url>
</repository>
</distributionManagement>
<repositories>
<repository>
<id>spring-snapshots</id>
<url>http://172.16.1.6:8081/nexus/content/repositories/spring.io/</url>
</repository>
<repository>
<id>nexus</id>
<name>Team Nexus Repository</name>
<url>http://172.16.1.6:8081/nexus/content/groups/public</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-snapshots</id>
<url>http://172.16.1.6:8081/nexus/content/repositories/spring.io/</url>
</pluginRepository>
<pluginRepository>
<id>nexus</id>
<name>Team Nexus Repository</name>
<url>http://172.16.1.6:8081/nexus/content/groups/public</url>
</pluginRepository>
</pluginRepositories>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skipTests>true</skipTests><!-- true跳过 false不跳过 -->
</configuration>
</plugin>
</plugins>
</build>
</project>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment