物理网IOT TCP服务端开发

TCP Server端实现,一定要用NIO来保证不被堵塞,否则将会造成服务器CPU飙升(切记,切记)

创建缓冲区(static map) 一定要用线程安全的map来实现,否则多个请求将造成map中存在您要的东西,而get为空的情况(切记),我这里用的:ConcurrentHashMap<String,SocketChannel> cacheThread =new ConcurrentHashMap<>();

 

主要包括以下几个部分
1.TCP server端开发
2.sh服务端启动脚本
3.服务端报文分析
4.静态json接口生成
5.TCP线程池清理
6.报文回复

 

1. server端源码(NIO实现,在用-超级稳定)

import com.google.gson.Gson;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

public class IOTServer {

   private int tcpPort = 9092;
   private String path = "";
   private static boolean cmdLock = true;
   private static long updateLog = 0;
   //更换为线程安全的map
   private static ConcurrentHashMap<String,SocketChannel> cacheThread =new ConcurrentHashMap<>();
   private Timer timer ;
   private int size = 256;//256k

   public void log(String msg){
       if(msg!=null&&!msg.equals("")){
           if(updateLog==0||updateLog<=System.currentTimeMillis()){
               System.out.println("clear.........");
               //清理
               String datetime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
               msg = datetime+" : "+msg;
               if(!"".equals(path)){
                   writeFile(path+ File.separator+"log.html",msg+"\r\n",false);
               }
               System.out.println(msg);
               updateLog= System.currentTimeMillis()+10*60*1000;//10分钟1次
           }else{
               //white log
               String datetime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
               msg = datetime+" : "+msg;
               if(!"".equals(path)){
                   writeFile(path+File.separator+"log.html",msg+"\r\n",true);
               }
               System.out.println(msg);
           }
       }
   }
    //append file
    private void writeFile(String fileFullPath,String content,boolean b) {
        FileOutputStream fos = null;
        try {
            File f = new File(fileFullPath);
            if(!f.exists()) f.createNewFile();//创建新文件
            //wt
            fos = new FileOutputStream(fileFullPath, b);
            fos.write(content.getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            if(fos != null){
                try {
                    fos.flush();
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

   public IOTServer(String path,String port,String size){
       this.tcpPort = Integer.parseInt(port);
       this.path = path;
       this.size = Integer.parseInt(size);
   }

   public void start() throws IOException {
       // Selector: multiplexor of SelectableChannel objects
       Selector selector = Selector.open(); // selector is open here
       // ServerSocketChannel: selectable channel for stream-oriented listening sockets
       ServerSocketChannel crunchifySocket = ServerSocketChannel.open();
       InetSocketAddress crunchifyAddr = new InetSocketAddress(tcpPort);
       // Binds the channel's socket to a local address and configures the socket to listen for connections
       crunchifySocket.bind(crunchifyAddr);
       // Adjusts this channel's blocking mode.
       crunchifySocket.configureBlocking(false);
       int ops = crunchifySocket.validOps();
       SelectionKey selectKy = crunchifySocket.register(selector, ops, null);
       log("Waiting client connect ... "+tcpPort);
       // Infinite loop..
       // Keep server running
       while (true) {

           // Selects a set of keys whose corresponding channels are ready for I/O operations
           selector.select();
           // token representing the registration of a SelectableChannel with a Selector
           Set<SelectionKey> crunchifyKeys = selector.selectedKeys();
           Iterator<SelectionKey> crunchifyIterator = crunchifyKeys.iterator();

           while (crunchifyIterator.hasNext()) {
               SelectionKey myKey = crunchifyIterator.next();

               // Tests whether this key's channel is ready to accept a new socket connection
               if (myKey.isAcceptable()) {
                   SocketChannel crunchifyClient = crunchifySocket.accept();
                   // Adjusts this channel's blocking mode to false
                   crunchifyClient.configureBlocking(false);
                   // Operation-set bit for read operations
                   crunchifyClient.register(selector, SelectionKey.OP_READ);
                   log("Connection Accepted: " + crunchifyClient.getLocalAddress() + "\n");
                   // Tests whether this key's channel is ready for reading
               } else if (myKey.isReadable()) {
                   SocketChannel crunchifyClient = (SocketChannel) myKey.channel();
                   try {
                       ByteBuffer crunchifyBuffer = ByteBuffer.allocate(size);
                       int readCount = crunchifyClient.read(crunchifyBuffer);
                       //获取did
                       String did = report(crunchifyBuffer.array(),readCount);
                       if (!did.equals("")) {
                           //晶合 002A00203235323916473831
                           if (did.length() == 24) {
                               //根据did去队列中获取命令,并更新命令状态

                               overJH(did, crunchifyClient);
                               log("close JH SocketChannel.");
                               crunchifyClient.close();
                           }
                           //精讯
                           if (did.length() == 12) {
                               //只有符合did的才开启线程,并传入SocketChannel/并把该did和Thread绑定记录到cache
                               cacheThread.put(did, crunchifyClient);
                               log("Waiting JX data. did->"+did+"\t isconnected->"+crunchifyClient.isConnected()+"\t"+"cacheThread size - >"+cacheThread.size()+"\t cacheThread keys:"+toKeys(cacheThread.keySet()) );
                               over(crunchifyClient,"01");
                           }
                       } else {
                           if("error".equals(did)){
                               crunchifyClient.close();
                           } else{
                               log("close Error SocketChannel.");
                               over(crunchifyClient,"00");
                               crunchifyClient.close();
                           }
                       }
                   }catch (Exception e){
                       //log(e.getLocalizedMessage());
                   }
               }
               crunchifyIterator.remove();
           }
       }
   }


   private String toKeys(Set<String> set){
       StringBuilder sb = new StringBuilder("");
       for(String s:set){
           sb.append(s+",");
       }
       return sb.toString();
   }

   private int cycleIndex = 0;

   public void cycle(){
       timer = new Timer();
       //3秒后获取执行命令
       timer.schedule(new TimerTask() {
           @Override
           public void run() {
               if(cmdLock){
                   cmdLock = false;

                   sendCmd();

                   if(cycleIndex>200){ //10分钟1次
                       log("----------- clear cmds ---------");

                       JDBC.checkCmd();

                       cycleIndex=0;
                   }
                   cycleIndex++;

                   cmdLock= true;
               }
           }
       },0,2950);
   }

    //发送命令
    public void sendCmd(){
        List<Map> cmdLines = JDBC.getCmd();
        for(Map line:cmdLines){ //循环执行可操作命令
            String cmd = (String) line.get("cmd");
            String did = (String) line.get("did");
            log("Get execute did->"+did+" cmd->"+cmd);
            if(cmd!=null && did!=null && did.length()==12){//精讯

                 SocketChannel socketChannel = cacheThread.get(did);
                 log("socketChannel - >"+socketChannel);

                 if(socketChannel!=null){
                    log("socketChannel connected ->"+socketChannel.isConnected()+"\t isOpen->"+socketChannel.isOpen());

                    try {
                        over(socketChannel, cmd);
                        JDBC.removeCmd(line.get("id").toString());
                        log("Execute cmd ok!");
                    }catch (Exception e){
                        log(e.getLocalizedMessage());
                    }
                 }
            }
        }
    }

    //callback
    public void overJH(String did,SocketChannel socketChannel){
        String cmdSQL = "select id,cmd from iot_cmds where did='"+did+"' and status=0 order by receive_time desc limit 1";
        List<Map> list =  JDBC.query(cmdSQL);
        if(list!=null&&list.size()>0){
            String cmd = (String)list.get(0).get("cmd");
            Integer id = (Integer)list.get(0).get("id");
            if(id!=null&&cmd!=null){//最新的命令未执行
                log("===JH==="+cmd+" id->"+id+" execute start.");
                try {
                    over(socketChannel, cmd);
                }catch (Exception e){
                   e.printStackTrace();
                }
                //更新命令状态
                JDBC.removeCmd(id+"");
                log("===JH==="+cmd+" execute ok.");
            }else{
                log("===JH==="+cmd+" id->"+id+" no execute.");
            }
        }else{
            log("===JH=== no cmd.");
        }
    }

   //over
    public void over(SocketChannel socketChannel,String newData) throws IOException {
        if(newData.startsWith("{")){
            ByteBuffer bb = ByteBuffer.allocate(newData.getBytes().length);
            bb.clear();
            bb.put(newData.getBytes());
            bb.flip();
            while (bb.hasRemaining()) {
                socketChannel.write(bb);
            }
        }else {
            ByteBuffer bb = ByteBuffer.allocate(toBytes(newData).length);
            bb.clear();
            bb.put(toBytes(newData));
            bb.flip();
            while (bb.hasRemaining()) {
                socketChannel.write(bb);
            }
        }
    }

    //写入json
    private void outJson(String datetime,String did,String awd,String asd,String sun,String co2,String ph,String lwd,String lsd,String ddv,
                           String phws,String phwd,String phqy,String phyl,
                           String UVA,String GH,String LD,String sTMP2,String sHR2,String sEC2,String sTMP3,String sHR3,String sEC3,

                           String sTMP4,String sHR4,String ph2,

                           String j01,String j02,String j03,String j04,String j05,String j06,String j07,String j08,String j09,String j0a,String bg,
                           int readCount,
                           String jb_time,String tf1_time,String tf2_time,String tf3_time,String js_time,String up_time){
        //json
        String json = "{\"datetime\":\""+datetime+"\"," +
                "\"did\":\""+did+"\"," +
                "\"awd\":\""+awd+"\"," +
                "\"asd\":\""+asd+"\"," +
                "\"sun\":\""+sun+"\"," +
                "\"co2\":\""+co2+"\"," +
                "\"ph\":\""+ph+"\"," +
                "\"lwd\":\""+lwd+"\"," +
                "\"lsd\":\""+lsd+"\"," +
                "\"ddv\":\""+ddv+"\"," +
                "\"phws\":\""+phws+"\"," +
                "\"phwd\":\""+phwd+"\"," +
                "\"phqy\":\""+phqy+"\"," +
                "\"phyl\":\""+phyl+"\"," +

                "\"uva\":\""+UVA+"\","+
                "\"gh\":\""+GH+"\","+
                "\"ld\":\""+LD+"\","+
                "\"stmp2\":\""+sTMP2+"\","+
                "\"shr2\":\""+sHR2+"\","+
                "\"sec2\":\""+sEC2+"\","+
                "\"stmp3\":\""+sTMP3+"\","+
                "\"shr3\":\""+sHR3+"\","+
                "\"sec3\":\""+sEC3+"\","+

                "\"stmp4\":\""+sTMP4+"\","+
                "\"shr4\":\""+sHR4+"\","+
                "\"ph2\":\""+ph2+"\"," +

                "\"j01\":\""+j01+"\"," +
                "\"j02\":\""+j02+"\"," +
                "\"j03\":\""+j03+"\"," +
                "\"j04\":\""+j04+"\"," +
                "\"j05\":\""+j05+"\"," +
                "\"j06\":\""+j06+"\"," +
                "\"j07\":\""+j07+"\"," +
                "\"j08\":\""+j08+"\"," +
                "\"j09\":\""+j09+"\"," +
                "\"j0a\":\""+j0a+"\"," +
                "\"bg\":\""+bg+"\"," +

                "\"bzise\":\""+readCount+"\"," +
                "\"jb_time\":\""+jb_time+"\"," +
                "\"tf1_time\":\""+tf1_time+"\"," +
                "\"tf2_time\":\""+tf2_time+"\"," +
                "\"tf3_time\":\""+tf3_time+"\"," +
                "\"js_time\":\""+js_time+"\"," +
                "\"up_time\":\""+up_time+"\"}";
        //输入到日志
        log(json);
        //写到json目录/did.json文件中
        writeJson(json,did);
    }

    private String FEDC01(String hex,String datetime,int readCount){
        try {
            String did = hex.substring(6,18); //did
            //上报数值
            String awd = hex.substring(32,40);//空气温度
            String asd = hex.substring(40,48);//空气湿度
            String lwd = hex.substring(48,56);//土壤温度
            String lsd = hex.substring(56,64);//土壤湿度
            String co2 = hex.substring(64,72);//二氧化碳
            String sun = hex.substring(72,80);//光照强度
            String ph = hex.substring(80,88);//土壤ph
            String ddv = hex.substring(88,96);//电导率
            //上报继电器
            String j01 = hex.substring(98,100);  //继电器01的状态
            String j02 = hex.substring(102,104); //继电器02的状态
            String j03 = hex.substring(106,108); //继电器03的状态
            String j04 = hex.substring(110,112); //继电器04的状态
            String j05 = hex.substring(114,116); //继电器05的状态
            String j06 = hex.substring(118,120); //继电器06的状态
            String j07 = hex.substring(122,124); //继电器07的状态
            String j08 = hex.substring(126,128); //继电器08的状态
            String j09 = hex.substring(130,132); //继电器09的状态
            String j0a = hex.substring(134,136); //继电器10的状态
            //卷被,通风1,通风2,通风3,背景,上报间隔
            String jb_time = hex.substring(136,140); //卷被时间间隔
            String tf1_time = hex.substring(140,144); //通风1时间间隔
            String tf2_time = hex.substring(144,148); //通风2时间间隔
            String tf3_time = hex.substring(148,152); //通风3的时间间隔
            String js_time = hex.substring(152,156); //浇水时间
            String bg = hex.substring(156,160);//背景图
            String up_time = hex.substring(160,164);//上报间隔
            //新增8,8,8,8

            String phws = "";//风速
            if(hex.length()>172) phws = hex.substring(164,172);
            String phwd = "";//风向
            if(hex.length()>180) phwd = hex.substring(172,180);
            String phqy = "";//气压
            if(hex.length()>188) phqy=hex.substring(180,188);
            String phyl = "";//雨量
            if(hex.length()>196) phyl=hex.substring(188,196);

            if(did!=null&&!did.equals("")){
                awd = trans(awd,true);
                asd = trans(asd,true);
                sun = trans(sun,false);
                co2 = trans(co2,false);
                ph = trans2(ph);
                lwd = trans(lwd,true);
                lsd = trans(lsd,true);
                ddv = trans(ddv,false);
                jb_time = trans10(jb_time);
                tf1_time = trans10(tf1_time);
                tf2_time = trans10(tf2_time);
                tf3_time = trans10(tf3_time);
                js_time = trans10(js_time);
                up_time = trans10(up_time);

                phws = trans(phws,true);
                phwd = trans(phwd,true);
                phqy = trans2(phqy);
                phyl = trans(phyl,false);

                //输出json
                outJson(datetime,did,awd,asd,sun,co2,ph,lwd,lsd,ddv,
                        phws,phwd,phqy,phyl,
                        "","","","","","","","","",
                        "","","",
                        j01,j02,j03,j04,j05,j06,j07,j08,j09,j0a,bg,
                        readCount,
                        jb_time,tf1_time,tf2_time,tf3_time,js_time,up_time);
            }
            return did;
        }catch (Exception e){}
        return "";
    }


    private String FEDC03(String hex,String datetime,int readCount){
        try {
            // FEDC03              6
            // 3E0BF337EF19        12
            // 0000004A03003C      14

            // 000000B1            40
            // 0000013B            48
            // 00000005            56
            // 00000000            64

            // 000000CE            72
            // 00000000            80
            // 000000D7            88
            // 00000000            96
            // 000000CF            104
            // 00000000            112
            // 000000D0            120
            // 00000000            128

            // 000002BC            136
            // 00000221            144

            // 00000014

            String did = hex.substring(6,18); //did
            //上报数值
            String awd = hex.substring(32,40);//空气温度
            String asd = hex.substring(40,48);//空气湿度
            String sun = hex.substring(48,56);//光照
            String co2 = hex.substring(56,64);//co2

            String lwd = hex.substring(64,72);//土壤温度
            String lsd = hex.substring(72,80);//土壤湿度

            String lwd1 = hex.substring(80,88);//土壤温度 1
            String lsd1 = hex.substring(88,96);//土壤湿度 1

            String lwd2 = hex.substring(96,104); //土壤温度 2
            String lsd2 = hex.substring(104,112); //土壤湿度 2

            String lwd3 = hex.substring(112,120); //土壤温度 3
            String lsd3 = hex.substring(120,128); //土壤湿度 3

            String ph = hex.substring(128,136); //土壤温度 4
            String ph1 = hex.substring(136,144); //土壤湿度 4

            if(did!=null&&!did.equals("")){
                awd = trans(awd,true);
                asd = trans(asd,true);
                sun = trans(sun,false);
                co2 = trans(co2,false);

                lwd = trans(lwd,true);
                lsd = trans(lsd,true);

                lwd1 = trans(lwd1,true);
                lsd1 = trans(lsd1,true);

                lwd2 = trans(lwd2,true);
                lsd2 = trans(lsd2,true);

                lwd3 = trans(lwd3,true);
                lsd3 = trans(lsd3,true);


                ph = trans2(ph);

                ph1 = trans2(ph1);

                //输出json
                outJson(datetime,did,awd,asd,sun,co2,ph,lwd,lsd,"",
                        "","","","",
                        "","","",lwd1,lsd1,"",lwd2,lsd2,"",
                        lwd3,lsd3,ph1,
                        "","","","","","","","","","","",
                        readCount,
                        "","","","","","");
            }
            return did;
        }catch (Exception e){}
        return "";
    }

    private String JH(byte[] bytes,int readCount){
        String result = new String(bytes).trim();
        log("JH->"+result);
        if(result!=null&&!result.equals("")){
            Map info = new Gson().fromJson(result,Map.class);
            String did = (String)info.get("U"); //设备id
            String t2 = info.get("t2").toString();//数据上报间隔

            List awds = (List)info.get("TMP"); //空气温度
            List asds = (List)info.get("HR");   //空气湿度
            List lwds = (List)info.get("sTMP"); //土壤温度
            List lsds = (List)info.get("sHR");  //土壤湿度
            List suns = (List)info.get("ILL");  //光照强度
            List co2s = (List)info.get("CO2");  //二氧化碳
            List phs = (List)info.get("sPH");  //ph值
            List ddvs = (List)info.get("sEC");  //电导率
            List phwss = (List)info.get("FS");  //风速
            List phwds = (List)info.get("FX");  //风向
            List phyls = (List)info.get("RV");  //雨量
            List phqys = (List)info.get("PRS");  //气压

            List UVAs = (List) info.get("UVA");//紫外线 w/㎡
            List GHs = (List) info.get("GH");//光合 w/㎡
            List LDs = (List) info.get("LD");//露点 °C

            List sTMP2s =  (List) info.get("sTMP2");//2号传感器 °C
            List sHR2s =  (List) info.get("sHR2");//2号传感器   %RH
            List sEC2s =  (List) info.get("sEC2");//2号传感器   us/cm

            List sTMP3s =  (List) info.get("sTMP3");//3号传感器
            List sHR3s =  (List) info.get("sHR3");//3号传感器
            List sEC3s =  (List) info.get("sEC3");//3号传感器

            //list
            String awd = tran100(awds,2);
            String asd = tran100(asds,2);
            String lwd = tran100(lwds,2);
            String lsd = tran100(lsds,2);
            String sun = tran100(suns,2);
            String co2 = tran100(co2s,0);
            String ph = tran100(phs,2);
            String ddv = tran100(ddvs,0);
            String phws = tran100(phwss,2);
            String phwd = fx100(phwds);
            String phyl = tran100(phyls,1);
            String phqy = tran100(phqys,2);

            String UVA = tran100(UVAs,1);
            String GH = tran100(GHs,0);
            String LD = tran100(LDs,1);

            String sTMP2 = tran100(sTMP2s,2);
            String sHR2 = tran100(sHR2s,2);
            String sEC2  = tran100(sEC2s,0);

            String sTMP3 = tran100(sTMP3s,2);
            String sHR3 = tran100(sHR3s,2);
            String sEC3  = tran100(sEC3s,0);

            String datetime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
            //json

            outJson(datetime,did,awd,asd,sun,co2,ph,lwd,lsd,ddv,
                    phws,phwd,phqy,phyl,
                    UVA,GH,LD,sTMP2,sHR2,sEC2,sTMP3,sHR3,sEC3,
                    "","","",
                    "","","","","","","","","","","",
                    readCount,
                    "","","","","","");

            return did;
        }
        return "";
    }



    public String report(byte[] bytes,int readCount){
        String hex = byteToHex(bytes);
        if(hex.startsWith("000000000")){ return "error"; }
        log("source->"+hex);
        if(hex!=null&&(hex.startsWith("FEDC01") || hex.startsWith("FEDC03") )){ //精讯
            String datetime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
            if(hex.startsWith("FEDC01")){
                log("JH->FEDC01-----------1");
                return FEDC01(hex,datetime,readCount);
            }
            if(hex.startsWith("FEDC03")){
                log("JH->FEDC03-----------2");
                return FEDC03(hex,datetime,readCount);
            }
        }else if(hex!=null&&(hex.startsWith("7B"))){ //晶合
           return JH(bytes,readCount);
        }else if(hex!=null&&(hex.length()>16)&&hex.substring(12,16).equals("AAAA")){
            return AA(hex,readCount);
        }else{
            log("Error head -> "+hex);
        }
        return "";
    }

    //我们自己的设备 4合一
    //send 26 20 44 68 22 18 AA AA 01 03 12 01 BE 00 76 00 00 00 00 00 00 03 11 00 00 00 00 00 32 84 1D
    //receive 260200440680220180AA0AA0010030120010B80000750000000000000000000020DC0000000000000000320F90BD
    // 262044682218AAAA
    // 01030C014300B800000000000000006631
    // 0103020015798B01
    // 0302FFFFB9F4
    // 01030400018894CC5C
    // 0103020000B844
    public String AA(String hex,int readCount){
       String did = hex.substring(0,16); //did
        log("AA->"+did);
        if("262044682218AAAA".equals(did)){
            String airsd = null;
            if(hex.length()>26) airsd = hex.substring(22,26);
            String airwd = null;
            if(hex.length()>30) airwd = hex.substring(26,30);
            String phws = null;
            if(hex.length()>60) phws = hex.substring(56,60);

            String phwd = null;
            if(hex.length()>74) phwd = hex.substring(70,74);

            String phqy = null;
            if(hex.length()>92) phqy = hex.substring(84,92);

            String phyl = null;
            if(hex.length()>106) phyl = hex.substring(102,106);


            airsd  = transAA(airsd,true);
            airwd  = transAA(airwd,true);

            phws = transAA(phws,true);
            phwd = transAA(phwd,false);
            log(phwd);
            //获得的数值为角度值,需要除以22.5 取整标识方向
            if(phwd!=null&&!phwd.equals("")){
               phwd  = (int)(Double.parseDouble(phwd)/22.5)+"";
            }

            log(phwd);
            phqy = trans2(phqy);
            phyl = transAA(phyl,true);

            String datetime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());

            outJson(datetime,did,airwd,airsd,"","","","","","",
                    phws,phwd,phqy,phyl,
                    "","","","","","","","","",
                    "","","",
                    "","","","","","","","","","","",
                    readCount,
                    "","","","","","");

        }

       return did;
    }

    private String transAA(String info,boolean xs){
        if(info==null||info.length()!=4) return "";
        String result =  Long.parseLong(info,16)+"";
        if(xs) result= Long.parseLong(info,16)*0.1+""; //空气温度
        DecimalFormat format = new DecimalFormat("0.00");
        return format.format(new BigDecimal(result));
    }

    //单位值转换
    private String tran100(List list,int level){
        String awd = "";
        if(list!=null&&list.size()>0){
            String tt =list.get(list.size()-1).toString();
            if(level==0) return tt;
            if(level==1){
                String result = Double.parseDouble(tt)/10+"";
                DecimalFormat format = new DecimalFormat("0.00");
                return format.format(new BigDecimal(result));
            }
            if(level==2){
                String result = Double.parseDouble(tt)/100+"";
                DecimalFormat format = new DecimalFormat("0.00");
                return format.format(new BigDecimal(result));
            }
        }
        return awd;
    }
    private String fx100(List list){
        String value = "";
        if(list!=null&&list.size()>0){
            String tt =list.get(list.size()-1).toString();
            if(tt.startsWith("0")) return "15";
            if(tt.startsWith("1")) return "1";
            if(tt.startsWith("2")) return "3";
            if(tt.startsWith("3")) return "5";
            if(tt.startsWith("4")) return "7";
            if(tt.startsWith("5")) return "9";
            if(tt.startsWith("6")) return "11";
            if(tt.startsWith("7")) return "13";
        }
        return value;
    }

    //16进制转具体值
    private String trans(String info,boolean xs){
        if(info==null||info.length()!=8) return "";
        String result =  Long.parseLong(info,16)+"";
        if(xs) result= Long.parseLong(info,16)*0.1+""; //空气温度
        DecimalFormat format = new DecimalFormat("0.00");
        return format.format(new BigDecimal(result));
    }

    private String trans2(String info){
        if(info==null||info.length()!=8) return "";
        String result = Long.parseLong(info,16)*0.01+"";
        DecimalFormat format = new DecimalFormat("0.00");
        return format.format(new BigDecimal(result));
    }

    //转10进制
    private String trans10(String info){
        if(info==null||info.length()!=4) return "";
        String result =  Long.parseLong(info,16)+"";
        return result;
    }

    /**
     * byte数组转hex
     * @param bytes
     * @return
     */
    private static final char[] HEX_CHAR = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
    public String byteToHex(byte[] bytes){
        char[] buf = new char[bytes.length * 2];
        int index = 0;
        for(byte b : bytes) { // 利用位运算进行转换,可以看作方法一的变种
            buf[index++] = HEX_CHAR[b >>> 4 & 0xf];
            buf[index++] = HEX_CHAR[b & 0xf];
        }

        return new String(buf);
    }
    /**
     * string转byte
     * @param str
     * */
    public static byte[] toBytes(String str) {
        if(str == null || str.trim().equals("")) {
            return new byte[0];
        }
        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;
    }

    //json make
    public void writeJson(String json,String id){
        writeFile(path+File.separator+"json"+File.separator+id+".json",json,false);
    }

   public static void main(String args[]) throws Exception{
       Properties pro = new Properties();
       pro.load(IOTServer.class.getClassLoader().getResourceAsStream("config.properties"));
       String port = pro.getProperty("PORT");
       String path = pro.getProperty("PATH");
       String size = pro.getProperty("SIZE");
       cacheThread.clear();//清掉缓存
       IOTServer is = new IOTServer(path,port,size);
       is.cycle(); //监听命令
       is.start();//启动server
   }
}

2. sh服务端脚本

#!/bin/sh
chmod 777 ./log.html
chmod 777 ./nohup.out
nohup java IOTServer & 

3. 物联网协议解析

 原报文
    EF BF BD EF BF BD 01 3E 0B EF BF BD EF BF BD EF BF BD EF BF BD 00 00 00 02 03 00 30 00 00 01 39 00 00 01 EF BF BD 00 00 00 EF BF BD 00 00 00 00 00 00 01 13 00 00 00 1B 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 EF BF BD 00 00 00 00 00 EF BF BD EF BF BD 01 3E 0B EF BF BD EF BF BD EF BF BD EF BF BD 00 00 00 04 03 00 30 00 00 01 39 00 00 01 EF BF BD 00 00 00 EF BF BD 00 00 00 00 00 00 01 13 00 00 00 1C 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 EF BF BD 00 00 00 00 00 EF BF BD EF BF BD 01 3E 0B EF BF BD EF BF BD EF BF BD EF BF BD 00 00 00 06 03 00 30 00 00 01 39 00 00 01 EF BF BD 00 00 00 EF BF BD 00 00 00 00 00 00 01 13 00 00 00 1D 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 EF BF BD 00 00 00 00 00 EF BF BD EF BF BD 01 3E 0B EF BF BD EF BF BD EF BF BD EF BF BD 00 00 00 08 03 00 30 00 00 01 39 00 00 01 EF BF BD 00 00 00 EF BF BD 00 00 00 00 00 00 01 13 00 00 00 1D 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 EF BF BD 00 00 00 00 00 EF BF BD EF BF BD 01 3E 0B EF BF BD EF BF BD EF BF BD EF BF BD 00 00 00

    转化后报文
    EF EF 01 3E 0B EF EF EF EF 00 00 00 02
    03 00 30
    00 00 01 39
    00 00 01 EF
    00 00 00 EF
    00 00 00 00
    00 00 01 13
    00 00 00 1B
    00 00 00 00
    00 00 00 00
    00 00 00 00
    00 00 00 00
    00 00 01 EF
    00 00 00 00
    00

    EF EF 01 3E 0B EF EF EF EF 00 00 00 04 03 00 30 00 00 01 39 00 00 01 EF 00 00 00 EF 00 00 00 00 00 00 01 13 00 00 00 1C 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 EF 00 00 00 00 00
    EF EF 01 3E 0B EF EF EF EF 00 00 00 06 03 00 30 00 00 01 39 00 00 01 EF 00 00 00 EF 00 00 00 00 00 00 01 13 00 00 00 1D 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 EF 00 00 00 00 00
    EF EF 01 3E 0B EF EF EF EF 00 00 00 08 03 00 30 00 00 01 39 00 00 01 EF 00 00 00 EF 00 00 00 00 00 00 01 13 00 00 00 1D 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 EF 00 00 00 00 00
    EF EF 01 3E 0B EF EF EF EF 00 00 00

     * 报文分析
     * EFEF01  为协议头 6位
     * EF EF 01 3E 0B EF EF EF EF 为设备id 12位
     * 00 00 00 02  SESSIONID  8位
     * 03 数据报头  2位
     * 00 30 数据字节长度  48字节 也就是说后边截取48位为数据   4位
     *              -----32位-----
     * 00 00 01 39 为温度,转10进制为313,每个单位代表0.1℃,则温度为      31.3℃      1
     * 00 00 01 EF 为空气湿度,转10进制为495,每个单位代表0.1%RH,则湿度为  49.5%RH    2
     * 00 00 00 EF 为光照强度,转10进制为239,每个单位代表239Lux,则光强为  239Lux     3
     * 00 00 00 00 为PH,转10进制为0,每个代为代表0.1,则PH为0,                       4
     * 00 00 01 13 为土壤温度,转10进制为275,每个单位代表0.1℃,则土壤温度为 27.5℃    5
     * 00 00 00 1B 为土壤湿度,转10进制为27,每个单位代表0.1%RH, 则土壤湿度为 2.7%RH   6
     * 00 00 00 00 为电导率,转10进制为0,每个单位代表1ug/cm,则电导率为      0ug/cm   7
     * 00 00 00 00 为有效辐射,转10进制为0,每个单位代表1W/㎡,则辐射为       0W/㎡    8
     * 00 00 00 00 为太阳总辐射,转10进制为0,每个单位代表1W/㎡,则总辐射为    0W/㎡    9
     * 00 00 00 00 为紫外线,转10进制为0,每个单位代表1W/㎡,则紫外线为    0W/㎡        10
     * 00 00 01 EF 为CO2浓度,转10进制为495,每个单位为1ppm,则CO2浓度为  495ppm        11
     * 00 00 00 00 为雨量,转10进制为0,每个单位为1mm,则雨量为    0mm                  12

server端报文日志

4.静态json接口生成

 //json make
    public void writeJson(String json,String id){
        writeFile(path+File.separator+"json"+File.separator+id+".json",json,false);
    }

把 json内容写到 应用服务器 json目录下/设备ID.json文件,外网可访问。(避免大量接口请求的压力)

json格式如下

{
	"datetime": "2019-06-18 18:12:03", //采集时刻
	"did": "3E0BEFEFEFEF", //设备id
	"awd": "30.20",//空气温度
	"asd": "49.5", //空气湿度
	"sun": "544", //光照强度
	"ph": "0.0", //ph值
	"lwd": "27.20", //土壤温度
	"lsd": "4.0",//土壤湿度
	"ddv": "0",//电导率
	"er": "0", //有效辐射
	"ar": "0", //总辐射
	"uv": "0", //紫外线
	"co2": "495", //二氧化碳浓度
	"rain": "0" //降雨量
}

感谢您的支持,写的文章如对您有所帮助,开源不易,请您打赏,谢谢啦~

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值