JAVA 实践项目 --- 树莓派信息自动化采集后入库项目 (四)

本贴最后更新于 2020 天前,其中的信息可能已经沧海桑田

项目源代码可访问我的 github:https://github.com/Spacider/Gather-and-store
如果觉得好的话请给个 star 哦~

开发 IDE: IDEA 2018.03 JDK 1.8
开发环境: macOS 10.13.6 (如 windows 请对项目中部分路径进行改写)
数据库: Oracle 11g


第三阶段:从日志文件中采集并发送数据

在 JAVA 实践项目---树莓派信息自动化采集后入库项目(三)中写到将数据写入日志文件中,接下来我们就要从日志文件中数据取出来并发送给 Server 端。
imagepng

此层项目结构为
imagepng


接下来开始看代码:
1.采集模块:

  • 定义一个 Gather 借口
public interface Gather  {
    /**
     * 采集模块接口实现
     * 对 src 下日志进行处理,一行日志封装成一个 Environment 对象或者两个 Environment 对象
     * 所有采集到的对象封装到集合中
     * @return
     */
    Collection<Environment> gather();
}

  • 有了接口之后再定义个包为 Impl,专门用来放实现类,在 Impl 下定义一个类为 GatherImpl,它实现了 Gather 接口。
public final class GatherImpl implements Gather  {
}

在实现类中写一个采集的主方法:

public Collection<Environment> gather(){
}

写方法实现之前想到一个问题:如果客户端发送到服务器的过程中出现意外怎么办?数据是否会丢失?会不会发送错行?
在经过考虑以后,想出一个解决方案:

使用 RandomAccessFile 流,它有一个 seek() 方法可以跳过之前已经读取过的字节数,这样的话我们每发送一次,就把已经发送的字节数储存在一个文件中,每次都读取这个文件,保证现在发的是上一次的末尾。

代码实现:

  • 读取储存文件,如果文件不存在,说明第一次运行,则创造一个新文件:
Properties properties = new Properties();
File positionFile = new File(“/Users/wjh/Desktop/FirstProject/src/main/resources/FilePostion.properties”);
if (!positionFile.exists()){
    positionFile.createNewFile();
}
properties.load(new FileReader(positionFile));
String FilePostion = properties.getProperty("FilePostion");
  • 跳过已经读取的字节数,并通过 String 类的 split 方法拆分字符串
while ((str = raf.readLine()) != null) {
    // 运用 | 来拆分字符串
    String[] stringList = str.split("\\|");
    getenv(stringList);
}

// 将最后的位数写回文件
properties.setProperty("FilePostion" , position+"");
pw = new PrintWriter(positionFile);
properties.store(pw,null);

getenv 方法的作用是根据所传入的拆分后的字符串来生成新的对象并返回,这里在实际与树莓派交互过程中出现了脏数据的情况,通过 if 语句来筛选出正确数据,实现:

private void getenv(String[] stringList){
    String sensorAddress = stringList[3];
    int FinalDate = 0;

    FinalDate = Integer.parseInt(stringList[6].substring(0, 4), 16);

    if (sensorAddress.equals("16")) {
        if (stringList[6].length() != 10){
	        System.out.println("得到的数据为脏数据, 温度湿度错误数据:" + stringList[6]);
        }else {
            /**
             * 温度计算公式:value(int) float Temperature = ((float)value*0.00268127)- 46.85;
             * 湿度:value(int) float Humidity = ((float)value*0.00190735)-6;
             */
            // 生成温度对象,并添加到 list 中
            float Temperature = (float) ((FinalDate * 0.00268127) - 46.85);
            environmentList.add(SetNameAndData(stringList, "温度", Temperature));

            // 生成湿度对象,并添加到 list 中
            FinalDate = Integer.parseInt(stringList[6].substring(4, 8), 16);
            float Humidity = (float) ((FinalDate * 0.00190735) - 6);
            environmentList.add(SetNameAndData(stringList, "湿度", Humidity));
        }
    }else if (sensorAddress.equals("256")){
        if (stringList[6].length() != 6) {
            System.out.println("得到的数据为脏数据, 光照错误数据:" + stringList[6]);
        }else{
            environmentList.add(SetNameAndData(stringList, "光照强度", FinalDate));
        }
    }else if (sensorAddress.equals("1280")){
        if (stringList[6].length() != 6) {
            System.out.println("得到的数据为脏数据, 二氧化碳错误数据:" + stringList[6]);
        }else{
            environmentList.add(SetNameAndData(stringList, "二氧化碳", FinalDate));
        }
    }else{
        System.out.println("得到的数据错误");
    }
}

SetNameAndData 方法为不同的 Enviroment 对象封装名字和数据:

private Environment SetNameAndData(String[] stringList, String name ,float Data){
    String sensorAddress = stringList[3];
    Environment envir = new Environment();
    try {
        envir.setSrcID(stringList[0]);
        envir.setDstID(stringList[1]);
        envir.setDevID(stringList[2]);
        envir.setSensorAddress(sensorAddress);
        envir.setCount(Integer.parseInt(stringList[4]));
        envir.setCmd(Integer.parseInt(stringList[5]));
        envir.setStatus(Integer.parseInt(stringList[7]));
        DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Timestamp ts = new Timestamp(format.parse(stringList[8]).getTime());
        envir.setGather_date(ts);
        envir.setName(name);
        envir.setData(Data);
    } catch (ParseException e) {
        logger.error("设置名字和数据失败");
    }

    return envir;
}

在 GatherImpl 的 gather() 方法中写一个打印语句:

for (Environment environment : environmentList) {
    System.out.println(environment);
}

写到这里,你就可以通过:

public static void main(String[] args) {
    GatherImpl gather = new GatherImpl();
    gather.gather();
}

来进行测试,最后打印出 environment 对象集说明书写正确。


2.发送模块

  • 同样,定义一个接口为 EnvClient:
public interface EnvClient extends WossModel {
    /**
     * 发送采集模块采集的集合对象
     */
    void send(Collection<Environment> col);
}
  • 有了接口以后写它的实现类 EnvClientImpl,它有一个很简单的功能,就是把上文封装好的对象发给服务器:
public class EnvClientImpl implements EnvClient  {
	public void send(Collection<Environment> col) {
	}
}

代码:

socket = new Socket(host,port);
os = socket.getOutputStream();
oos = new ObjectOutputStream(os);
// 运用对象流把生成的对象发给 Server 端
oos.writeObject(col);
oos.flush();

写好这一切以后,定义这一阶段的的主入口,把内容串起来:

public final class ClientMain {

    /**
     * 集合 Client 并提供向外的入口
     * 通过采集所获得的 list 发给 Server
     */
    public static void ClientSendMain(){
        ConfigurationImpl configuration = new ConfigurationImpl();
        Gather gather = configuration.getGather();
        List<Environment> environmentList = (List <Environment>) gather.gather();
        configuration.getClient().send(environmentList);
    }
}
  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3168 引用 • 8207 回帖
  • 实践项目
    6 引用

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...

推荐标签 标签

  • JRebel

    JRebel 是一款 Java 虚拟机插件,它使得 Java 程序员能在不进行重部署的情况下,即时看到代码的改变对一个应用程序带来的影响。

    26 引用 • 78 回帖 • 623 关注
  • CodeMirror
    1 引用 • 2 回帖 • 119 关注
  • OnlyOffice
    4 引用 • 23 关注
  • jsDelivr

    jsDelivr 是一个开源的 CDN 服务,可为 npm 包、GitHub 仓库提供免费、快速并且可靠的全球 CDN 加速服务。

    5 引用 • 31 回帖 • 45 关注
  • webpack

    webpack 是一个用于前端开发的模块加载器和打包工具,它能把各种资源,例如 JS、CSS(less/sass)、图片等都作为模块来使用和处理。

    41 引用 • 130 回帖 • 295 关注
  • Flume

    Flume 是一套分布式的、可靠的,可用于有效地收集、聚合和搬运大量日志数据的服务架构。

    9 引用 • 6 回帖 • 594 关注
  • 反馈

    Communication channel for makers and users.

    123 引用 • 906 回帖 • 193 关注
  • 资讯

    资讯是用户因为及时地获得它并利用它而能够在相对短的时间内给自己带来价值的信息,资讯有时效性和地域性。

    53 引用 • 85 回帖
  • PWL

    组织简介

    用爱发电 (Programming With Love) 是一个以开源精神为核心的民间开源爱好者技术组织,“用爱发电”象征开源与贡献精神,加入组织,代表你将遵守组织的“个人开源爱好者”的各项条款。申请加入:用爱发电组织邀请帖
    用爱发电组织官网:https://programmingwithlove.stackoverflow.wiki/

    用爱发电组织的核心驱动力:

    • 遵守开源守则,体现开源&贡献精神:以分享为目的,拒绝非法牟利。
    • 自我保护:使用适当的 License 保护自己的原创作品。
    • 尊重他人:不以各种理由、各种漏洞进行未经允许的抄袭、散播、洩露;以礼相待,尊重所有对社区做出贡献的开发者;通过他人的分享习得知识,要留下足迹,表示感谢。
    • 热爱编程、热爱学习:加入组织,热爱编程是首当其要的。我们欢迎热爱讨论、分享、提问的朋友,也同样欢迎默默成就的朋友。
    • 倾听:正确并恳切对待、处理问题与建议,及时修复开源项目的 Bug ,及时与反馈者沟通。不抬杠、不无视、不辱骂。
    • 平视:不诋毁、轻视、嘲讽其他开发者,主动提出建议、施以帮助,以和谐为本。只要他人肯努力,你也可能会被昔日小看的人所超越,所以请保持谦虚。
    • 乐观且活跃:你的努力决定了你的高度。不要放弃,多年后回头俯瞰,才会发现自己已经成就往日所仰望的水平。积极地将项目开源,帮助他人学习、改进,自己也会获得相应的提升、成就与成就感。
    1 引用 • 487 回帖 • 6 关注
  • DNSPod

    DNSPod 建立于 2006 年 3 月份,是一款免费智能 DNS 产品。 DNSPod 可以为同时有电信、网通、教育网服务器的网站提供智能的解析,让电信用户访问电信的服务器,网通的用户访问网通的服务器,教育网的用户访问教育网的服务器,达到互联互通的效果。

    6 引用 • 26 回帖 • 521 关注
  • 深度学习

    深度学习(Deep Learning)是机器学习的分支,是一种试图使用包含复杂结构或由多重非线性变换构成的多个处理层对数据进行高层抽象的算法。

    40 引用 • 40 回帖 • 1 关注
  • Vditor

    Vditor 是一款浏览器端的 Markdown 编辑器,支持所见即所得、即时渲染(类似 Typora)和分屏预览模式。它使用 TypeScript 实现,支持原生 JavaScript、Vue、React 和 Angular。

    313 引用 • 1667 回帖 • 1 关注
  • HBase

    HBase 是一个分布式的、面向列的开源数据库,该技术来源于 Fay Chang 所撰写的 Google 论文 “Bigtable:一个结构化数据的分布式存储系统”。就像 Bigtable 利用了 Google 文件系统所提供的分布式数据存储一样,HBase 在 Hadoop 之上提供了类似于 Bigtable 的能力。

    17 引用 • 6 回帖 • 45 关注
  • Firefox

    Mozilla Firefox 中文俗称“火狐”(正式缩写为 Fx 或 fx,非正式缩写为 FF),是一个开源的网页浏览器,使用 Gecko 排版引擎,支持多种操作系统,如 Windows、OSX 及 Linux 等。

    7 引用 • 30 回帖 • 452 关注
  • Node.js

    Node.js 是一个基于 Chrome JavaScript 运行时建立的平台, 用于方便地搭建响应速度快、易于扩展的网络应用。Node.js 使用事件驱动, 非阻塞 I/O 模型而得以轻量和高效。

    138 引用 • 268 回帖 • 194 关注
  • 笔记

    好记性不如烂笔头。

    304 引用 • 777 回帖
  • Latke

    Latke 是一款以 JSON 为主的 Java Web 框架。

    70 引用 • 532 回帖 • 712 关注
  • Hprose

    Hprose 是一款先进的轻量级、跨语言、跨平台、无侵入式、高性能动态远程对象调用引擎库。它不仅简单易用,而且功能强大。你无需专门学习,只需看上几眼,就能用它轻松构建分布式应用系统。

    9 引用 • 17 回帖 • 597 关注
  • SSL

    SSL(Secure Sockets Layer 安全套接层),及其继任者传输层安全(Transport Layer Security,TLS)是为网络通信提供安全及数据完整性的一种安全协议。TLS 与 SSL 在传输层对网络连接进行加密。

    69 引用 • 190 回帖 • 495 关注
  • OkHttp

    OkHttp 是一款 HTTP & HTTP/2 客户端库,专为 Android 和 Java 应用打造。

    16 引用 • 6 回帖 • 54 关注
  • OpenStack

    OpenStack 是一个云操作系统,通过数据中心可控制大型的计算、存储、网络等资源池。所有的管理通过前端界面管理员就可以完成,同样也可以通过 Web 接口让最终用户部署资源。

    10 引用 • 6 关注
  • 区块链

    区块链是分布式数据存储、点对点传输、共识机制、加密算法等计算机技术的新型应用模式。所谓共识机制是区块链系统中实现不同节点之间建立信任、获取权益的数学算法 。

    91 引用 • 751 回帖
  • Kotlin

    Kotlin 是一种在 Java 虚拟机上运行的静态类型编程语言,由 JetBrains 设计开发并开源。Kotlin 可以编译成 Java 字节码,也可以编译成 JavaScript,方便在没有 JVM 的设备上运行。在 Google I/O 2017 中,Google 宣布 Kotlin 成为 Android 官方开发语言。

    19 引用 • 33 回帖 • 26 关注
  • Kubernetes

    Kubernetes 是 Google 开源的一个容器编排引擎,它支持自动化部署、大规模可伸缩、应用容器化管理。

    108 引用 • 54 回帖
  • SendCloud

    SendCloud 由搜狐武汉研发中心孵化的项目,是致力于为开发者提供高质量的触发邮件服务的云端邮件发送平台,为开发者提供便利的 API 接口来调用服务,让邮件准确迅速到达用户收件箱并获得强大的追踪数据。

    2 引用 • 8 回帖 • 439 关注
  • Vue.js

    Vue.js(读音 /vju ː/,类似于 view)是一个构建数据驱动的 Web 界面库。Vue.js 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件。

    261 引用 • 662 回帖
  • Elasticsearch

    Elasticsearch 是一个基于 Lucene 的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于 RESTful 接口。Elasticsearch 是用 Java 开发的,并作为 Apache 许可条款下的开放源码发布,是当前流行的企业级搜索引擎。设计用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。

    116 引用 • 99 回帖 • 269 关注