一、单片机->Wifi

1整体框架图

springer通讯作者的标注方式 通讯作者标注在哪里_网络

2注意事项

1.重新上电=开始编程
复位=一直透传

2.将wifi同时连上USB转TTL,再连上电脑

用XCOM打开非单片机串口的串口,可以看到WiFi模块发出去的指令

用XCOM用单片机的串口,可以看到该串口的输出,即printf的内容

springer通讯作者的标注方式 通讯作者标注在哪里_springer通讯作者的标注方式_02

springer通讯作者的标注方式 通讯作者标注在哪里_网络_03

3遇到的坑

3.1给单片机编程的软件界面如下,一定要点“编程后执行”

springer通讯作者的标注方式 通讯作者标注在哪里_kafka_04

springer通讯作者的标注方式 通讯作者标注在哪里_单片机_05

3.2串口2一直发不出去数据给设备,可能是因为网口转串口模块被reset了

解决办法:

springer通讯作者的标注方式 通讯作者标注在哪里_kafka_06


网口转串口模块连上USB转TTL,再连上电脑,打开上面的软件,将界面按照下面的来配置

springer通讯作者的标注方式 通讯作者标注在哪里_elasticsearch_07

二、单片机->4G

1花生壳的配置

springer通讯作者的标注方式 通讯作者标注在哪里_elasticsearch_08


springer通讯作者的标注方式 通讯作者标注在哪里_springer通讯作者的标注方式_09


springer通讯作者的标注方式 通讯作者标注在哪里_elasticsearch_10

2 XCOM的配置

springer通讯作者的标注方式 通讯作者标注在哪里_elasticsearch_11

二、WiFi->Logstash

1.配置WiFi,打开XCOM,用AT指令

1.1多条发送

AT          //测试模块是否能正常通讯,返回"ok"即为正常
AT+CWMODE=3         //配置成 AP+STA模式
AT+RST          //重启生效
AT+CWJAP="xuhui","11111111"         //连接电脑热点“xuhui”为热点的名称,"11111111"为密码

2.配置logstash目录下的itcast-wifi.conf

input {
    tcp {
        port => 5044
        mode => "server"
        ssl_enable => false
    }
}

filter{
	mutate{
	   split => ["message",","]   #按,进行split切割message
			add_field => {
			    "name" => "%{[message][0]}"
			}
			add_field => {
			    "age" => "%{[message][1]}"
			}
	}
}

output {
    stdout { codec => rubydebug }
}

3.启动logstash

进入logstash-8.1.2主目录,cmd
写命令:

logstash -f itcast-wifi.conf

4.配置WiFi

4.1多条发送

AT+CIPSTART="TCP","192.168.137.1",5044          //本机IP,logstash端口号
AT+CIPMODE=1         //开启透传模式
AT+CIPSEND         //开始透传

4.2单条发送

xuhui,20

5.Logstash输出截图

springer通讯作者的标注方式 通讯作者标注在哪里_elasticsearch_12

三、Logstash->Kafka

1.启动Zookeeper

进入zookeeper的bin文件,cmd

zkServer

2.启动Kafka

2.1启动Kafka

进入Kafka主目录文件,cmd

.\bin\windows\kafka-server-start.bat .\config\server.properties

2.2创建一个Topic

进入Kafka的bin\windows文件,cmd

kafka-topics.bat --create --bootstrap-server localhost:9092 --replication-factor 1 --partitions 1 --topic kafkatest0427

2.3查看创建的topic

kafka-topics.bat --list --bootstrap-server localhost:9092

2.4启动生产者 producer

直接在创建完Topic的命令行界面输入以下命令

kafka-console-producer.bat --broker-list localhost:9092 --topic kafkatest0427

2.5启动消费者customer

进入Kafka的bin\windows文件,cmd

kafka-console-consumer.bat --bootstrap-server localhost:9092 --topic kafkatest0427 --from-beginning

3.修改Logstash的SCM-wifi-logstash-kafka.conf

input {
	tcp {
        port => 5044
        mode => "server"
        ssl_enable => false
    }
}

filter{
	mutate{
	   split => ["message",","]   #按 , 进行split切割message
			add_field => {
			    "name" => "%{[message][0]}"
			}
			add_field => {
			    "age" => "%{[message][1]}"
			}
	}
}

output {  
	kafka {
		bootstrap_servers => "192.168.137.1:9092" #kafka服务器地址
		topic_id => "kafkatest0427"
		batch_size => 5
		codec => "json" #写入的时候使用json编码,因为logstash收集后会转换成json格式
    }
}

4.启动Logstash

进入logstash-8.1.2主目录,cmd
写命令:

logstash -f SCM-wifi-logstash-kafka.conf

5.Wifi模块发送单条指令

xuhui,20

6.消费者界面截图

springer通讯作者的标注方式 通讯作者标注在哪里_单片机_13

7.遇到的坑

7.1

WARN [AdminClient clientId=adminclient-1] Connection to node -1 (localhost/127.0.0.1:9092) could not be established. Broker may not be available. (org.apache.kafka.clients.NetworkClient)
  1. 修改kafka中server.properties配置
  2. 同时,在kafka中创建topic 、生产者、消费者的时候,也要在指令中进行以下改动

7.2

ZooKeeper audit is disabled

在 zkServer.cmd 添加"-Dzookeeper.audit.enable=true",如下图所示

springer通讯作者的标注方式 通讯作者标注在哪里_网络_14

7.3

ERROR Shutdown broker because all log dirs in D:\develop\Kafka\kafka_2.13-3.1.0\kafka-logs have failed (kafka.log.LogManager)

删除错误信息中的目录(D:\develop\Kafka\kafka_2.13-3.1.0\kafka-logs)下的所有文件,然后重启Kafka

使用maven官方仓库直接下载项目需要的jar包方法
1.首先我们得知道我们需要下载那个jar包,本文中我们以 mysql-connector-java.jar 包为例。

2.打开maven在线仓库,https://mvnrepository.com/

3.我们在搜索框输入jar包名:mysql-connector-java,如图能够找到对应的jar
4.然后我们点击上图标注位置(红色框)进入选择我们需要的jar版本

  1. 进入页面下载jar包,如下图(备注,有的jar不是点击jar进行,点击view All,大家可以自己试着去点)

java学习——IDEA导入jar包并调用

项目目录下新建 lib 目录,并将需要导入的 jar 包复制到该文件夹

如:(以导入 mysql驱动包为例)

springer通讯作者的标注方式 通讯作者标注在哪里_springer通讯作者的标注方式_15

将 lib 目录下的所有依赖导入到指定模块

打开 File -> Project Structure (Ctrl + Shift + Alt + S)-> 点击 加号 -> 选择我们创建的 lib 目录 -> 确认即可

springer通讯作者的标注方式 通讯作者标注在哪里_springer通讯作者的标注方式_16


然后选择需要该依赖的模块,点击 OK

springer通讯作者的标注方式 通讯作者标注在哪里_elasticsearch_17


此时我们打开该模块的依赖,可以看到 lib 下的依赖已经导入成功

springer通讯作者的标注方式 通讯作者标注在哪里_springer通讯作者的标注方式_18


导入成功后该jar包还可以打开查看源码 (▽)

springer通讯作者的标注方式 通讯作者标注在哪里_elasticsearch_19


如何导入 com.alibaba.fastjson.JSONObject

1: 先在百度搜索 : 从github上阿里 fastJson包

springer通讯作者的标注方式 通讯作者标注在哪里_springer通讯作者的标注方式_20


2: 点击下载 jar包 (注意maven是中央仓,可以在配置文件中配置自动下载)

springer通讯作者的标注方式 通讯作者标注在哪里_网络_21


注:记得下载.jar,不要下载javadoc.jar和sources.jar

springer通讯作者的标注方式 通讯作者标注在哪里_elasticsearch_22

四、写入服务

1.用java(Maven)写一个工程,从Kafka中获取数据,并发到ES

1.1参考链接


1.2自己的代码

class KafkaPoolData

import org.apache.kafka.clients.consumer.ConsumerConfig;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.apache.kafka.clients.consumer.ConsumerRecords;
import org.apache.kafka.clients.consumer.KafkaConsumer;
import org.apache.kafka.common.TopicPartition;

import java.io.IOException;
import java.time.Duration;
import java.util.*;

public class KafkaPoolData {
    private KafkaConsumer<String, String> consumer;
    private String topic;

    public KafkaPoolData(String topic) {
        Properties consumerConfig = new Properties();

        consumerConfig.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092");//连接Kafka
        consumerConfig.put(ConsumerConfig.GROUP_ID_CONFIG, "xh-source-group1"); //消费者组,保证要跟其他的不一样
        consumerConfig.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest");// 这个参数指定了当消费者第一次读取分区或者上一次的位置太老(比如消费者下线时间太久)时的行为,可以取值为latest(读取消息队列中最新的消息)或者earliest(从最老的消息开始消费)
        /**kafka根据key值确定消息发往哪个分区(如果分区被指定则发往指定的分区),具有相同key的消息被发往同一个分区,如果key为NONE则随机选择分区,可以使用key_serializer参数序列化为字节类型
         value为要发送的消息值,必须为bytes类型,如果这个值为空,则必须有对应的key值,并且空值被标记为删除。可以通过配置value_serializer参数序列化为字节类型*/

        //设置值反序列化器
        consumerConfig.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringDeserializer");
        //设置key反序列化器
        consumerConfig.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringDeserializer");  //用来做反序列化的,也就是将字节数组转换成对象

        //创建一个消费者
        consumer = new KafkaConsumer<>(consumerConfig);
        this.topic = topic;
    }

    public void testConsumer(long offset,int number) throws IOException {
        //与subscirbe方法不同,assign方法由用户直接手动consumer实例消费哪些具体分区,assign的consumer不会拥有kafka的group management机制,也就是当group内消费者数量变化的时候不会有reblance行为发生。assign的方法不能和subscribe方法同时使用。
        TopicPartition partition = new TopicPartition(topic, 0);//i是指定分区partition

        consumer.assign(Arrays.asList(partition));
        consumer.seek(partition, offset);// 指定从这个topic和partition的哪个位置获取

        //consumer.close(); //主动关闭可以使得Kafka立即进行重平衡而不需要等待会话过期

        int count = 0;
        System.out.println("\nConsumer begin!\n");
        System.out.println("\nConsumer data begin!\n");
        ConsumerRecords<String, String> records = consumer.poll(Duration.ofMillis(1000)); //拉取消费记录

        System.out.println("开始读取消息");
        System.out.println("---------------"+records.count());
        for (ConsumerRecord<String, String> record : records) {
            //获取字符串数据
            String text = record.value();
            //输出字符串数据
            System.out.println(text);

            //生成随机id
            UUID uuid = UUID.randomUUID();
            String id = uuid.toString();

            //将text id输出到ES
            PutDataToEs02.PutToEs(text,id);

            count++;

            //count大于拉取数据时,停止拉取数据
            if (count > number) {
                break;
            }
        }
        //System.out.println("\nParse data Finished! count=" + count + "\n");
        System.out.println("\nConsumer Finished!\n");
    }

    public static void main(String[] args) throws IOException {
        //初始化ES
        PutDataToEs02.initClient();
        //Write2Es.initClient();

        //topic名称
        String topic = "kafkatest0427";
        //String topic = args[0];
        long offset =80; //从哪里开始
        // long offset = Long.parseLong(args[0]);
        int number=175;  //需要拉取多少数据
        // int number = Integer.parseInt(args[1]);
        KafkaPoolData kafkaconsumer = new KafkaPoolData(topic);
        kafkaconsumer.testConsumer(offset,number);
        PutDataToEs02.closeClient();
        //Write2Es.closeClient();
    }
}

class PutDataToEs02

import com.alibaba.fastjson.JSONObject;
import org.apache.http.HttpHost;
import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.action.DocWriteResponse;

import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;

import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;

import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;

import org.elasticsearch.rest.RestStatus;

import java.io.IOException;


public class PutDataToEs02 {
    private static RestHighLevelClient client = null;

    public static void initClient() {
        //连接ES
        client = new RestHighLevelClient(
                RestClient.builder(new HttpHost("192.168.137.1", 9200, "http")));//ES的本地端口号
        System.out.println(client);
    }

    //关闭服务
    public static void closeClient() throws IOException {
        client.close();
    }

    public static void PutToEs(String text, String id) throws IOException {
        //将字符串text转成JSON
        JSONObject jsonObject = JSONObject.parseObject(text);
        String message = "";
        String timestamp = "";

        //提取text里面的message
        if (jsonObject.containsKey("message")) {
            message = jsonObject.getString("message");
            //System.out.println(message1);
        }
        //提取text里面的timestamp
        if (jsonObject.containsKey("@timestamp")) {
            timestamp = jsonObject.getString("@timestamp");
            //System.out.println(timestamp);
        }

        //1.创建索引请求
        IndexRequest request = new IndexRequest("kafkatoes0429","data",id);

        //2.用XContentBuilder来构建文档
        XContentBuilder builder = XContentFactory.jsonBuilder();
        builder.startObject();
        {
            builder.field("timestamp", timestamp);
            builder.field("message", message);
        }
        builder.endObject();
        request.source(builder);

        //3.发送请求
        //3.1 同步方式发送请求
        IndexResponse indexResponse = null;
        try {
            indexResponse = client.index(request, RequestOptions.DEFAULT);
        } catch(ElasticsearchException e) {
            //捕获,并处理异常
            //判断是否版本冲突、create但文档已存在冲突
            if (e.status() == RestStatus.CONFLICT) {
                System.out.println("版本冲突\n" + e.getDetailedMessage());
            }
            System.out.println("索引异常");
        }

        //4.处理响应
        if(indexResponse != null) {
            String index = indexResponse.getIndex();
            String type = indexResponse.getType();
            String id1 = indexResponse.getId();
            //long version = indexResponse.getVersion();
        if (indexResponse.getResult() == DocWriteResponse.Result.CREATED) {
            System.out.println("新增文档成功\n" + "index = " + index + " type = " + type + " id = " + id1);
        } else if (indexResponse.getResult() == DocWriteResponse.Result.UPDATED) {
            System.out.println("修改文档成功\n" + "index = " + index + " type = " + type + " id = " + id1);
        }
        // 分片处理信息
        /*ReplicationResponse.ShardInfo shardInfo = indexResponse.getShardInfo();
        if (shardInfo.getTotal() != shardInfo.getSuccessful()) {

        }
        // 如果有分片副本失败,可以获得失败原因信息
        if (shardInfo.getFailed() > 0) {
            for (ReplicationResponse.ShardInfo.Failure failure : shardInfo.getFailures()) {
                String reason = failure.reason();
                System.out.println("副本失败原因:" + reason);
            }
        }*/
        }
    }
}
1.3java控制台的截图

springer通讯作者的标注方式 通讯作者标注在哪里_elasticsearch_23

2.输出到Elasticsearch的截图

springer通讯作者的标注方式 通讯作者标注在哪里_kafka_24

五、grafana

1.启动grafana

进入bin目录,通过执行grafana-server.exe启动Grafana

2.登录grafana

打开浏览器并转到http://localhost:3000/,然后登录即可,默认用户和密码均为admin