| | |
| | | package com.dy.common.mw.protocol; |
| | | |
| | | import java.net.URI; |
| | | import java.util.HashMap; |
| | | import java.util.List; |
| | | import java.util.Set; |
| | | |
| | | import com.dy.common.util.ClassScan; |
| | | import org.reflections.Reflections; |
| | | |
| | | |
| | | public abstract class Driver { |
| | |
| | | protected HashMap<String, Class<CodeParse>> downCode2Class = new HashMap<>() ; |
| | | protected HashMap<String, CodeParse> downCode2ClassInstance = new HashMap<>() ; |
| | | |
| | | protected Notify notify ; |
| | | |
| | | /** |
| | | * 清空自己 |
| | | */ |
| | | public abstract void clear() ; |
| | | |
| | | /** |
| | | * 设置RTU信息通知器 |
| | | * @param notify 通知 |
| | | */ |
| | | public void setNotify(Notify notify){ |
| | | this.notify = notify ; |
| | | } |
| | | |
| | | /** |
| | | * 单线程单例Driver模式下运行 |
| | | * 扫描识别功能码注解类 |
| | | * @throws Exception 异常 |
| | | */ |
| | | public abstract void scanAnnotationCode() throws Exception ; |
| | | |
| | | /** |
| | | * 扫描识别功能码注解类 |
| | | * @param driver 驱动 |
| | | * @param protocolName 协议名称 |
| | | * @param uri URI |
| | | * @param scanRootPackage 扫描包 |
| | | * @throws Exception 异常 |
| | | */ |
| | | @SuppressWarnings("unchecked") |
| | | protected void doScanAnnotationCode(Driver driver, String protocolName, URI uri, String scanRootPackage) throws Exception{ |
| | | ClassLoader load = driver.getClass().getClassLoader() ; |
| | | List<String> classNames = new ClassScan().searchClassFromUrl(new URI[]{uri}, scanRootPackage) ; |
| | | if(classNames != null && classNames.size() > 0){ |
| | | String code ; |
| | | String[] codes ; |
| | | for(String cName : classNames){ |
| | | String className = cName.substring(0, cName.lastIndexOf('.')) ; |
| | | Class<?> clazz = load.loadClass(className) ; |
| | | Class<CodeParse> codeParseClazz ; |
| | | if(clazz.isAnnotationPresent(AnnotationCodeUp.class)){ |
| | | AnnotationCodeUp ann = clazz.getAnnotation(AnnotationCodeUp.class) ; |
| | | if(ann != null){ |
| | | codeParseClazz = (Class<CodeParse>)clazz ; |
| | | codes = ann.ifAny() ; |
| | | if(codes.length > 0){ |
| | | for(String cd: codes){ |
| | | cd = cd.trim() ; |
| | | if(!(cd.trim().equals(""))){ |
| | | if(driver.upCode2Classes.containsKey(cd)){ |
| | | throw new Exception("严重错误,协议" + protocolName + "的上行数据功能码" + cd + "出现了重复注解!") ; |
| | | } |
| | | driver.upCode2Classes.put(cd, codeParseClazz) ; |
| | | protected void doScanAnnotationCode(Driver driver, String protocolName, String scanRootPackage) throws Exception{ |
| | | Reflections reflections = new Reflections(scanRootPackage); // 指定包名 |
| | | String code ; |
| | | String[] codes ; |
| | | Class<CodeParse> codeParseClazz ; |
| | | |
| | | Set<Class<?>> codeUpClasses = reflections.getTypesAnnotatedWith(AnnotationCodeUp.class); |
| | | if (codeUpClasses != null && codeUpClasses.size() > 0) { |
| | | for (Class<?> clazz : codeUpClasses) { |
| | | AnnotationCodeUp ann = clazz.getAnnotation(AnnotationCodeUp.class) ; |
| | | if(ann != null){ |
| | | codeParseClazz = (Class<CodeParse>)clazz ; |
| | | codes = ann.ifAny() ; |
| | | if(codes.length > 0){ |
| | | for(String cd: codes){ |
| | | cd = cd.trim() ; |
| | | if(!(cd.trim().equals(""))){ |
| | | if(driver.upCode2Classes.containsKey(cd)){ |
| | | throw new Exception("严重错误,协议" + protocolName + "的上行数据功能码" + cd + "出现了重复注解!") ; |
| | | } |
| | | driver.upCode2Classes.put(cd, codeParseClazz) ; |
| | | } |
| | | }else{ |
| | | code = ann.value().trim() ; |
| | | if(!(code.equals(""))){ |
| | | if(driver.upCode2Classes.containsKey(code)){ |
| | | throw new Exception("严重错误,协议" + protocolName + "的上行数据功能码" + code + "出现了重复注解!") ; |
| | | } |
| | | driver.upCode2Classes.put(code, codeParseClazz) ; |
| | | } |
| | | }else{ |
| | | code = ann.value().trim() ; |
| | | if(!(code.equals(""))){ |
| | | if(driver.upCode2Classes.containsKey(code)){ |
| | | throw new Exception("严重错误,协议" + protocolName + "的上行数据功能码" + code + "出现了重复注解!") ; |
| | | } |
| | | driver.upCode2Classes.put(code, codeParseClazz) ; |
| | | } |
| | | } |
| | | } |
| | | |
| | | if(clazz.isAnnotationPresent(AnnotationCodeDown.class)){ |
| | | AnnotationCodeDown ann = clazz.getAnnotation(AnnotationCodeDown.class) ; |
| | | if(ann != null){ |
| | | codeParseClazz = (Class<CodeParse>)clazz ; |
| | | codes = ann.ifAny() ; |
| | | if(codes.length > 0){ |
| | | for(String cd: codes){ |
| | | cd = cd.trim() ; |
| | | if(!(cd.trim().equals(""))){ |
| | | if(driver.downCode2Class.containsKey(cd)){ |
| | | throw new Exception("严重错误,协议驱动" + protocolName + "的下行数据功能码" + cd + "出现了重复注解!") ; |
| | | } |
| | | driver.downCode2Class.put(cd, codeParseClazz) ; |
| | | } |
| | | } |
| | | |
| | | Set<Class<?>> codeDownClasses = reflections.getTypesAnnotatedWith(AnnotationCodeDown.class); |
| | | if (codeDownClasses != null && codeDownClasses.size() > 0) { |
| | | for (Class<?> clazz : codeDownClasses) { |
| | | AnnotationCodeDown ann = clazz.getAnnotation(AnnotationCodeDown.class) ; |
| | | if(ann != null){ |
| | | codeParseClazz = (Class<CodeParse>)clazz ; |
| | | codes = ann.ifAny() ; |
| | | if(codes.length > 0){ |
| | | for(String cd: codes){ |
| | | cd = cd.trim() ; |
| | | if(!(cd.trim().equals(""))){ |
| | | if(driver.downCode2Class.containsKey(cd)){ |
| | | throw new Exception("严重错误,协议驱动" + protocolName + "的下行数据功能码" + cd + "出现了重复注解!") ; |
| | | } |
| | | driver.downCode2Class.put(cd, codeParseClazz) ; |
| | | } |
| | | }else{ |
| | | code = ann.value() ; |
| | | if(!(code.trim().equals(""))){ |
| | | if(driver.downCode2Class.containsKey(code)){ |
| | | throw new Exception("严重错误,协议驱动" + protocolName + "的下行数据功能码" + code + "出现了重复注解!") ; |
| | | } |
| | | driver.downCode2Class.put(code, codeParseClazz) ; |
| | | } |
| | | }else{ |
| | | code = ann.value() ; |
| | | if(!(code.trim().equals(""))){ |
| | | if(driver.downCode2Class.containsKey(code)){ |
| | | throw new Exception("严重错误,协议驱动" + protocolName + "的下行数据功能码" + code + "出现了重复注解!") ; |
| | | } |
| | | driver.downCode2Class.put(code, codeParseClazz) ; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 单线程单例Driver模式下运行 |
| | | * 得到上行数据功能码处理类CodeParse对象 |
| | |
| | | return codeParse ; |
| | | } |
| | | /** |
| | | * 解析电信平台上行数据 |
| | | * 解析RTU上行数据 |
| | | * @param isLowPower 是否在低功耗环境下运行 |
| | | * @param rtuAddr 控制器地址 |
| | | * @param upBuffer 字节数组 |