一、介绍系统
本系统简单来说就是一个蓝牙水控系统,通过蓝牙控制开关水,并计算用水量和用水价格,很适用于高校的热水系统。
二、系统功能
1.系统构成
系统大致主要分为软件和硬件两大部分,硬件部分主要有单片机(STM32)、蓝牙模块(ECB02H2)、水流量传感器(YFS201C)、继电器这几部分组成;软件部分主要是android小程序和onenet云平台。
2.系统功能
功能:整个系统就是app通过手机蓝牙发送open指令,硬件接收到open指令后,打开继电器,开始供水,水流量传感器就开始采集计算用水量,并通过用水量计算出费用,并且2秒实时将瞬时流量、累计流量、费用,通过蓝牙模块发送到安卓小程序上,安卓小程序接收到数据后,通过手机网络将数据上传至onenet云平台,最后也可以通过手机app端发送close,关闭继电器。
3.系统框架图
三、硬件程序
1.水流量传感器驱动和采集程序:
.c文件
#include "YFS201C.h"
GOLBAL_FLOW golbal_flow;
int time1=0;
#define Flow_Model_4 1 //4分管定义为1;6分管定义为0
#define MODE_4_K 5.0f
#define MODE_4_PLUSE_CNT_1L 300.0f
#define MODE_6_K 5.5f
#define MODE_6_PLUSE_CNT_1L 330.0f
#define FLOW_FULL 1000000
//用PD2的外部中断来获取低电平的脉冲
void Exit2_Config(void)
{
EXTI_InitTypeDef EXTI_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
//**********映射配置**************
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource4);
//Config EXTI4 line
EXTI_ClearITPendingBit(EXTI_Line4);
EXTI_InitStructure.EXTI_Line = EXTI_Line4;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //下降沿触发中断
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = EXTI4_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
EXTI->IMR &= ~(EXTI_Line4);
}
void EXTI4_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line4) != RESET)
{
golbal_flow.pluse_1s++; //下降沿采集脉冲数
}
EXTI_ClearITPendingBit(EXTI_Line4); //清除Line4的中断标志位
}
void Flow_Read(void)
{
if(golbal_flow.receive_flag)
{
if(golbal_flow.pluse_1s > 0)
{
#ifdef Flow_Model_4
/*计算公式:
累计流量 = 对瞬时流量做积分
= (脉冲频率 / 300个脉冲) //1L需要300个脉冲,脉冲频率HZ
*/
golbal_flow.acculat += golbal_flow.pluse_1s / MODE_4_PLUSE_CNT_1L; //单位L
/*计算公式:
瞬时流量 = (脉冲频率 / 300个脉冲) * 60s
= 脉冲频率 / 5.0(流量系K)
*/
golbal_flow.instant = golbal_flow.pluse_1s / MODE_4_K; //单位(L/min)
#else
/*计算公式:
累计流量 = 对瞬时流量做积分
= (脉冲频率 / 330个脉冲) //1L需要330个脉冲,脉冲频率HZ
*/
golbal_flow.acculat += golbal_flow.pluse_1s / MODE_6_PLUSE_CNT_1L; //单位L
/*计算公式:
瞬时流量 = ((脉冲频率 + 3) / 330个脉冲) * 60s
= (脉冲频率 + 3) / 5.5(流量系K)
*/
golbal_flow.instant = (golbal_flow.pluse_1s + 3) / MODE_6_K; //单位(L/min)
#endif
if(golbal_flow.acculat >= FLOW_FULL)
{
golbal_flow.acculat = 0;
}
}
else
{
golbal_flow.instant = 0;
}
//1升=0.001m^3 3.5¥/m^3
golbal_flow.money=(golbal_flow.acculat*0.001)*3.5;
printf("瞬间流量:%.2f(L/min) 累计流量:%.2f(L) money:%.2f\n",golbal_flow.instant,golbal_flow.acculat,golbal_flow.money);
golbal_flow.receive_flag = 0; //接收完成标志位清零
golbal_flow.pluse_1s = 0;
}
}
void TIM3_Int_Init(u16 arr,u16 psc)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //①时钟 TIM3 使能
//定时器 TIM3 初始化
TIM_TimeBaseStructure.TIM_Period = arr; //设置自动重装载寄存器周期的值
TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置时钟频率除数的预分频值
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM 向上计数
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //初始化 TIM3
TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE ); //允许更新中断
//中断优先级 NVIC 设置
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; //TIM3 中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //先占优先级 0 级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //从优先级 3 级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ 通道被使能
NVIC_Init(&NVIC_InitStructure); //④初始化 NVIC 寄存器
TIM_Cmd(TIM3, ENABLE); //⑤使能 TIM3
TIM3->CR1 &= ~(0x01);
}
//定时器 3 中断服务程序
void TIM3_IRQHandler(void) //TIM3 中断
{
if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //检查 TIM3 更新中断发生与否
{
TIM_ClearITPendingBit(TIM3, TIM_IT_Update ); //清除 TIM3 更新中断标志
golbal_flow.receive_flag = 1;
time1++;
}
}
.h文件
#ifndef _YFS201C_H
#define _YFS201C_H
#include "stm32f10x.h"
#include "usart.h"
typedef struct
{
uint8_t receive_flag; //多久读取标志位
uint16_t pluse_1s; //脉冲频率
float instant; //瞬时流量
float acculat; //累计流量
float money;
}GOLBAL_FLOW;
extern GOLBAL_FLOW golbal_flow;
void Exit2_Config(void);
void Flow_Read(void);
void TIM3_Int_Init(u16 arr,u16 psc);
#endif
2.识别手机app端发送的消息指令
u8 rxbuff[30] = {0};
int flag=0,count_open=0,count_close=0;
int flag1=0;
void USART3_IRQHandler(void)
{
u8 res;
static u8 index = 0;
if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET)
{
if(index>=29) //发生溢出
{
index=0;
memset(rxbuff,0,30);
}
res = USART_ReceiveData(USART3);
rxbuff[index] = res;
index++;
}
if(strstr((char *)rxbuff,"open"))
{
if(flag1==0)
{
flag1=1;
if(flag!=1) flag=1;
count_open++;
}
memset(rxbuff,0,30);
index=0;
}
else if(strstr((char *)rxbuff,"close"))
{
if(flag1==1)
{
flag1=0;
if(flag!=0) flag=0;
count_close++;
}
memset(rxbuff,0,30);
index=0;
}
USART_ClearFlag(USART3,USART_FLAG_TC);
}
3.控制开和关的逻辑程序
if(flag)
{
TIM3->CR1 |= 0x01;
EXTI->IMR |= EXTI_Line4;
relay=1;
if(count_open==2 && count_close==1)
{
count_close=0;
count_open=1;
golbal_flow.instant=golbal_flow.acculat=golbal_flow.money=0;
}
if(count_open>2) count_open=0;
}
else
{
if(count_close>1) count_close=0;
TIM3->CR1 &= ~(0x01);
EXTI->IMR &= ~(EXTI_Line4);
relay=0;
}
//bulebooth send data
if(time1>=2)
{
time1=0;
UsartPrintf3("ins:%.1f sum:%.1f money:%.2f\r\n",golbal_flow.instant,golbal_flow.acculat,golbal_flow.money);
delay_ms(3000);
}
以上就是硬件实现的程序,水流量传感器信号端输出的就是脉冲,所以就用的外部中断来获取这个信号量就很合适。
四、软件程序
1.蓝牙库程序
package cn.eciot.ble_demo_java;
import android.Manifest;
import android.annotation.SuppressLint;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.content.pm.PackageManager;
import android.location.LocationManager;
import android.os.Build;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.core.app.ActivityCompat;
import java.util.ArrayList;
import java.util.List;
interface ECBluetoothAdapterStateChangeCallback {
void callback(boolean ok, int errCode, String errMsg);
}
interface ECBluetoothDeviceFoundCallback {
void callback(String id, String name, String mac, int rssi);
}
interface ECBLEConnectionStateChangeCallback {
void callback(boolean ok, int errCode, String errMsg);
}
interface ECBLECharacteristicValueChangeCallback {
void callback(String str, String strHex);
}
public class ECBLE {
private static BluetoothAdapter bluetoothAdapter = null;
private static ECBluetoothAdapterStateChangeCallback ecBluetoothAdapterStateChangeCallback = (boolean ok, int errCode, String errMsg) -> {
};
static void onBluetoothAdapterStateChange(ECBluetoothAdapterStateChangeCallback cb) {
ecBluetoothAdapterStateChangeCallback = cb;
}
static void openBluetoothAdapter(Context ctx) {
bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (bluetoothAdapter == null) {
ecBluetoothAdapterStateChangeCallback.callback(false, 10000, "此设备不支持蓝牙");
return;
}
if (!bluetoothAdapter.isEnabled()) {
ecBluetoothAdapterStateChangeCallback.callback(false, 10001, "请打开设备蓝牙开关");
return;
}
LocationManager locationManager = (LocationManager) ctx.getSystemService(Context.LOCATION_SERVICE);
boolean gps = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
boolean network = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
if (!(gps || network)) {
ecBluetoothAdapterStateChangeCallback.callback(false, 10002, "请打开设备定位开关");
return;
}
ecBluetoothAdapterStateChangeCallback.callback(true, 0, "");
if (bluetoothGatt != null) {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) {
if (ActivityCompat.checkSelfPermission(ctx, Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) {
return;
}
}
bluetoothGatt.close();
}
}
//--------------------------------------------------------------------------------------------
private static final List<BluetoothDevice> deviceList = new ArrayList<>();
private static boolean scanFlag = false;
private static ECBluetoothDeviceFoundCallback ecBluetoothDeviceFoundCallback = (String id, String name, String mac, int rssi) -> {
};
static void onBluetoothDeviceFound(ECBluetoothDeviceFoundCallback cb) {
ecBluetoothDeviceFoundCallback = cb;
}
private static final BluetoothAdapter.LeScanCallback leScanCallback = (BluetoothDevice bluetoothDevice, int rssi, byte[] bytes) -> {
try {
// Log.e("bytes",bytesToHexString(bytes));
// String name = getBluetoothName(bytes);
@SuppressLint("MissingPermission")
String name = bluetoothDevice.getName();
if (name == null || name.equals("")) return;
String mac = bluetoothDevice.getAddress();
if (mac == null || mac.equals("")) return;
mac = mac.replace(":", "");
// Log.e("bleDiscovery", name + "|" + mac +"|"+ rssi);
boolean isExist = false;
for (BluetoothDevice tempDevice : deviceList) {
if (tempDevice.getAddress().replace(":", "").equals(mac)) {
isExist = true;
break;
}
}
if (!isExist) {
deviceList.add(bluetoothDevice);
}
ecBluetoothDeviceFoundCallback.callback(mac, name, mac, rssi);
}catch (Throwable e){
Log.e("LeScanCallback","Throwable");
}
};
static void startBluetoothDevicesDiscovery(Context ctx) {
if (!scanFlag) {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) {
if (ActivityCompat.checkSelfPermission(ctx, Manifest.permission.BLUETOOTH_SCAN) != PackageManager.PERMISSION_GRANTED) {
return;
}
}
if (bluetoothAdapter != null) {
bluetoothAdapter.startLeScan(leScanCallback);
scanFlag = true;
}
}
}
static void stopBluetoothDevicesDiscovery(Context ctx) {
if (scanFlag) {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) {
if (ActivityCompat.checkSelfPermission(ctx, Manifest.permission.BLUETOOTH_SCAN) != PackageManager.PERMISSION_GRANTED) {
return;
}
}
if (bluetoothAdapter != null) {
bluetoothAdapter.stopLeScan(leScanCallback);
scanFlag = false;
}
}
}
//--------------------------------------------------------------------------------------------
private static BluetoothGatt bluetoothGatt = null;
private static boolean connectFlag = false;
private static int reconnectTime = 0;
private static ECBLEConnectionStateChangeCallback ecBLEConnectionStateChangeCallback = (boolean ok, int errCode, String errMsg) -> {
};
static void onBLEConnectionStateChange(ECBLEConnectionStateChangeCallback cb) {
ecBLEConnectionStateChangeCallback = cb;
}
private static ECBLEConnectionStateChangeCallback connectCallback = (boolean ok, int errCode, String errMsg) -> {
};
private static ECBLECharacteristicValueChangeCallback ecBLECharacteristicValueChangeCallback = (String str, String hexStr) -> {
};
static void onBLECharacteristicValueChange(ECBLECharacteristicValueChangeCallback cb) {
ecBLECharacteristicValueChangeCallback = cb;
}
private static final String ecCharacteristicWriteUUID = "0000fff2-0000-1000-8000-00805f9b34fb";
private static final String ecCharacteristicNotifyUUID = "0000fff1-0000-1000-8000-00805f9b34fb";
private static BluetoothGattCharacteristic ecCharacteristicWrite;
private static final BluetoothGattCallback bluetoothGattCallback = new BluetoothGattCallback() {
@SuppressLint("MissingPermission")
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
super.onConnectionStateChange(gatt, status, newState);
Log.e("onConnectionStateChange", "status=" + status + "|" + "newState=" + newState);
if (status != BluetoothGatt.GATT_SUCCESS) {
gatt.close();
if(connectFlag){
ecBLEConnectionStateChangeCallback.callback(false,10000,"onConnectionStateChange:" + status + "|" + newState);
}else{
connectCallback.callback(false,10000,"onConnectionStateChange:" + status + "|" + newState);
}
connectFlag = false;
return;
}
if (newState == BluetoothProfile.STATE_CONNECTED) {
gatt.discoverServices();
connectCallback.callback(true,0,"");
ecBLEConnectionStateChangeCallback.callback(true,0,"");
connectFlag = true;
return;
}
if (newState == BluetoothProfile.STATE_DISCONNECTED) {
gatt.close();
if(connectFlag){
ecBLEConnectionStateChangeCallback.callback(false, 0, "");
}else {
connectCallback.callback(false, 0, "");
}
connectFlag = false;
}
}
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
super.onServicesDiscovered(gatt, status);
bluetoothGatt = gatt;
List<BluetoothGattService> bluetoothGattServices = bluetoothGatt.getServices();
for (BluetoothGattService service : bluetoothGattServices) {
Log.e("ble-service", "UUID=" + service.getUuid().toString());
List<BluetoothGattCharacteristic> listGattCharacteristic = service.getCharacteristics();
for (BluetoothGattCharacteristic characteristic : listGattCharacteristic) {
Log.e("ble-char", "UUID=:" + characteristic.getUuid().toString());
//notify
// if ((characteristic.getProperties() & BluetoothGattCharacteristic.PROPERTY_NOTIFY) > 0) {
if(characteristic.getUuid().toString().equals(ecCharacteristicNotifyUUID)){
notifyBLECharacteristicValueChange(characteristic);
}
//write
if (characteristic.getUuid().toString().equals(ecCharacteristicWriteUUID)) {
ecCharacteristicWrite = characteristic;
}
}
}
new Thread(()->{
try {
Thread.sleep(300);
setMtu();
} catch (Throwable e) {
e.printStackTrace();
}
}).start();
}
@Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
super.onCharacteristicChanged(gatt, characteristic);
byte[] bytes = characteristic.getValue();
if (bytes != null) {
String str = new String(bytes);
String strHex = bytesToHexString(bytes);
Log.e("ble-receive", "读取成功[string]:" + str);
Log.e("ble-receive", "读取成功[hex]:" + strHex);
ecBLECharacteristicValueChangeCallback.callback(str, strHex);
}
}
@Override
public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) {
super.onMtuChanged(gatt, mtu, status);
if (BluetoothGatt.GATT_SUCCESS == status) {
Log.e("BLEService", "onMtuChanged success MTU = " + mtu);
} else {
Log.e("BLEService", "onMtuChanged fail ");
}
}
};
@SuppressLint("MissingPermission")
private static void notifyBLECharacteristicValueChange(BluetoothGattCharacteristic characteristic) {
boolean res = bluetoothGatt.setCharacteristicNotification(characteristic, true);
if (!res) {
return;
}
for (BluetoothGattDescriptor dp : characteristic.getDescriptors()) {
dp.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
bluetoothGatt.writeDescriptor(dp);
}
}
@SuppressLint("MissingPermission")
private static void setMtu() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
bluetoothGatt.requestMtu(247);
}
}
@SuppressLint("MissingPermission")
static void closeBLEConnection() {
if (bluetoothGatt != null) {
bluetoothGatt.disconnect();
}
connectFlag = false;
}
private static void _createBLEConnection(Context ctx, String id) {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S){
if (ActivityCompat.checkSelfPermission(ctx, Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) {
connectCallback.callback(false,10001,"permission error");
return;
}
}
if (bluetoothGatt != null) {
bluetoothGatt.close();
}
for (BluetoothDevice tempDevice : deviceList) {
if (tempDevice.getAddress().replace(":", "").equals(id)) {
bluetoothGatt = tempDevice.connectGatt(ctx, false, bluetoothGattCallback);
return;
}
}
connectCallback.callback(false, 10002, "id error");
}
static void createBLEConnection(Context ctx, String id) {
reconnectTime = 0;
connectCallback = (boolean ok, int errCode, String errMsg) -> {
Log.e("connectCallback", ok + "|"+ errCode + "|"+ errMsg);
if(!ok){
reconnectTime = reconnectTime + 1;
if(reconnectTime>4){
reconnectTime = 0;
ecBLEConnectionStateChangeCallback.callback(false, errCode, errMsg);
}else{
new Thread(()->{
try {
Thread.sleep(300);
_createBLEConnection(ctx,id);
} catch (Throwable e) {
e.printStackTrace();
}
}).start();
}
}
};
_createBLEConnection(ctx,id);
}
@SuppressLint("MissingPermission")
static void writeBLECharacteristicValue(String data, boolean isHex) {
byte[] byteArray = isHex ? hexStrToBytes(data) : data.getBytes();
ecCharacteristicWrite.setValue(byteArray);
//设置回复形式
ecCharacteristicWrite.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE);
//开始写数据
bluetoothGatt.writeCharacteristic(ecCharacteristicWrite);
}
//--------------------------------------------------------------------------------------------
@NonNull
private static String bytesToHexString(byte[] bytes){
if (bytes == null) return "";
StringBuilder str = new StringBuilder();
for (byte b : bytes) {
str.append(String.format("%02X", b));
}
return str.toString();
}
@NonNull
private static byte[] hexStrToBytes(@NonNull String hexString){
int len = hexString.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(hexString.charAt(i), 16) << 4)
+ Character.digit(hexString.charAt(i+1), 16));
}
return data;
}
@NonNull
private static String getBluetoothName(byte[] bytes){
for(int i=0;i<62;i++){
if(i>=bytes.length) return "";
int tempLen = bytes[i];
int tempType = bytes[i+1];
if((tempLen==0)||(tempLen>30)){
return "";
}
if((tempType == 9)||(tempType == 8)){
byte[] nameBytes = new byte[tempLen-1];
System.arraycopy(bytes,i+2,nameBytes,0,tempLen-1);
return new String(nameBytes);
}
i+=tempLen;
}
return "";
}
}
2.蓝牙连接程序
void uiInit(){
SwipeRefreshLayout swipeRefreshLayout = findViewById(R.id.swipe_layout);
swipeRefreshLayout.setColorSchemeColors(0x01a4ef);
swipeRefreshLayout.setOnRefreshListener(()->{
deviceListData.clear();
deviceListDataShow.clear();
listViewAdapter.notifyDataSetChanged();
new Handler().postDelayed(()->{
swipeRefreshLayout.setRefreshing(false);
//权限
permissionsInit();
},1000);
});
ListView listView = findViewById(R.id.list_view);
listViewAdapter = new Adapter(this, R.layout.list_item, deviceListDataShow);
listView.setAdapter(listViewAdapter);
listView.setOnItemClickListener((AdapterView<?> adapterView, View view, int i, long l)->{
showConnectDialog();
DeviceInfo deviceInfo = (DeviceInfo)listView.getItemAtPosition(i);
ECBLE.onBLEConnectionStateChange((boolean ok, int errCode, String errMsg)-> runOnUiThread(()->{
hideConnectDialog();
if (ok) {
// ECBLE.stopBluetoothDevicesDiscovery(this);
startActivities(new Intent[]{new Intent().setClass(this, DeviceActivity.class)});
} else {
showToast("蓝牙连接失败,errCode="+errCode+",errMsg="+errMsg);
showAlert("提示","蓝牙连接失败,errCode="+errCode+",errMsg="+errMsg,()->{});
}
}));
ECBLE.createBLEConnection(this,deviceInfo.id);
});
listRefresh();
}
3.接收硬件传输的数据
ECBLE.onBLECharacteristicValueChange((String str,String strHex)-> runOnUiThread(()->{
//获取当前时间,并格式化为字符串,用于显示在接收的数据前面,以标记接收时间
@SuppressLint("SimpleDateFormat") String timeStr = new SimpleDateFormat("[HH:mm:ss,SSS]: ").format(new Date(System.currentTimeMillis()));
String nowStr = receiveDataTextView.getText().toString();
//将数据传递到解析函数
Data_parse(str);
//if()hex显示-----else()字符串显示
if (hexRevCheckBox.isChecked()) {
receiveDataTextView.setText(nowStr + timeStr + strHex.replaceAll("(.{2})","$1 ") + "\r\n");
} else {
receiveDataTextView.setText(nowStr + timeStr + str + "\r\n");
}
if (scrollCheckBox.isChecked()) {
scrollView.post(()-> scrollView.fullScroll(ScrollView.FOCUS_DOWN));
}
}));
4.接收到数据解析程序
void Data_parse(String str_data)
{
// 初始化三个字符串变量
double ins = 0.0;
double sum = 0.0;
double money = 0.0;
// 切割字符串,以空格为分隔符
String[] dataParts = str_data.split("\\s+");
// 遍历切割得到的部分,提取数值部分
for (String part : dataParts) {
if (part.startsWith("ins:")) {
String valueString = part.substring(4); // 从"ins:"后开始提取
ins = Double.parseDouble(valueString);
} else if (part.startsWith("sum:")) {
String valueString = part.substring(4);
sum = Double.parseDouble(valueString);
} else if (part.startsWith("money:")) {
String valueString = part.substring(6);
money = Double.parseDouble(valueString);
}
}
//传递提取出来的值
post_data(ins,sum,money);
}
5.数据上云程序
void post_data(double ins, double sum, double money)
{
new Thread(() -> {
String url = "http://api.heclouds.com/devices/1109836136/datapoints";
OkHttpClient okHttpClient = new OkHttpClient();
// 构建要发送的三个消息
String messages = "{\"datastreams\":[";
messages += "{\"id\":\"ins\",\"datapoints\":[{\"value\":" + ins + "}]},";
messages += "{\"id\":\"sum\",\"datapoints\":[{\"value\":" + sum + "}]},";
messages += "{\"id\":\"money\",\"datapoints\":[{\"value\":" + money + "}]}";
messages += "]}";
RequestBody requestBody = RequestBody.create(MediaType.parse("application/json"), messages);
Request request = new Request.Builder()
.url(url)
.addHeader("api-key", "wOzqMSmKBkBHXICV2P0Ud565Uno=")
.addHeader("Content-Type", "application/json")
.post(requestBody)
.build();
Call call = okHttpClient.newCall(request);
try {
Response response = call.execute();
if (response.code() == 200) {
String string = response.body().string();
Log.e("应答", string);
} else {
Log.e("错误", "请求失败,响应码:" + response.code());
}
} catch (IOException e) {
e.printStackTrace();
Log.e("异常", "请求异常:" + e.getMessage());
}
}).start();
}
五、总结
在此过程中也遇到过很多问题,其中有个问题是运行模拟机的时候正常运行,但是将APK安装在手机上,也就是运行真机的时候就会出现闪退的情况,遇到这种情况,最好的解决办法就是用根数据线连接到电脑,进行在线仿真调试,这样就能够对症下药。
给大家展示一下效果图吧!
下面是两个不同的界面,第一幅是滚动显示接收的数据,第二幅是文本显示数据。
手机端接收到一组数据,就会往云端发送一组数据。