物联网专业课程设计:温室监控系统——移动终端篇(LineChart、SQLite( 二 )


4.数据库存储模块设计
支持、Linux等主流操作系统,所需内存很少,并且能够与很多程序语言相结合 。由于移动设备平台的内存和外存都受到限制,因此不能执行非常复杂的数据库相关功能 。根据具有的轻量级、简单易用、配置简单等特点,综上考虑,嵌入式数据库为本次设计最佳选择 。
由于一个种植园具有多个温室,一个温室可能具有几十个监控节点,每一次采集都会有巨量的数据被存入数据库,这对数据库和手机设备会造成很大的负荷,故本设计中数据库只保存最近半小时的数据,对其他时间段数据进行删除 。
根据提供的一些API类,重写类的构造方法创建数据库,然后调用()方法获取对数据库的读写权限 。
关键代码如下:
dbOpenHelper = new MyDBOpenHelper(getApplicationContext(), "SC_Database.db", null, 1);//调用数据库类,选择SC_Database.db数据表dbReader = dbOpenHelper.getReadableDatabase();//读操作dbWriter = dbOpenHelper.getWritableDatabase();//写操作listViewAdapter = new SimpleCursorAdapter(getApplicationContext(), R.layout.item_list, result,new String[]{"device", "trwendu", "trshidu","hwendu","hshidu","guangq","dianliu","shijian"},new int[]{R.id.device, R.id.trwendu, R.id.trshidu,R.id.hwendu,R.id.hshidu,R.id.guangq,R.id.dianliu,R.id.shijian},CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);listView.setAdapter(listViewAdapter);//初始化ListView控件
效果如下:
移动终端接收上位机转发的数据并实时显示出来,如左图所示,可以看到界面显示土壤温湿度、环境温湿度、光强、电流的数据,并在下方的图表区域每个2s进行一次打点,在图表上向右滑动,还可以看到历史数据 。
移动终端将接收的数据存储至内部数据库中,并通过一个显示出当前数据库的信息,触摸界面上下滑动可查看更久之前的数据,效果如右图所示,设备代表温室号,表明目前手机端采集的是温室1的数据,在最后的时间那一栏为采集时间,表示这条数据是什么时候采集的,方便管理员进行数据分析 。
串口助手充当检测/控制终端,测试手机能否将指令发送至串口助手,根据已经配置好的虚拟串口,我在手机端的设备状态界面点击想要打开或关闭的监控节点,设置温度阈值,点击下方的发送按钮,系统便会将各个开关按钮的点击事件数据集合成一串字符串,按照帧格式要求发送至上位机,再由上位机通过串口发送至检测/控制终端 。如第一张图所示,在手机界面上显示了各个设备的状态,均为关闭状态,此时我将温度下限设为11,温度上限设为35,打开顶开窗、湿帘风机、环流风机按钮,其他监控节点为关闭状态,点击“指令下达”按钮,可以看到如第二张图所示的上位机界面,上位机消息栏提示“手机发送指令”信息,并在阈值设定区域更新对应数据,此时串口助手接收栏那里显示上位机转发的数据,如第三张图所示,串口助手显示“#001#”字样,与数据帧格式进行比对为正确数据格式 。
全部代码:
数据显示界面public class WifiActivity extends AppCompatActivity {final private int UDP_RECEIVE_BUFFER_LENGTH = 1024;final private int SENSOR_FRAME_LENGTH = 15;final private String TDS_LINE_COLOR = "#0000FF";final private String TEMP_LINE_COLOR = "#00FF00";final private String HUM_LINE_COLOR = "#FF0000";final private String LIGHT_LINE_COLOR = "#00FFFF";private SQLiteDatabase dbWriter;private MyDBOpenHelper dbOpenHelper;private int[] frameBuffer = new int[SENSOR_FRAME_LENGTH];private int frameByteCount = 0;private Socket socket;private LineChart turangwenduChart;private LineChart turangshiduChart;private LineChart huanjingshiduChart;private LineChart guangqiangChart;private LineChart huanjingwenduChart;private LineChart dianliuChart;private Handler mMainHandler;private TextView turangwendu;private TextView turangshidu;private TextView huanjingshidu;private TextView guangqiang;private TextView huanjingwendu;private TextView dianliu;String tuwen,tushi,huanwen,huanshi,guangq,dianl,shijian;String waizheyang_state="0",dingkaichuang_state="0",cekaichuang_state="0",shilian_state="0",zhouliufengji_state="0";String neizheyang_state="0";String huanliufengji_state="0",wuhua_state,guangai_state="0";String shebei="1";int year,month,day,hour,minute,second;int tuwen1,tushi1,huanwen1,huanshi1,guangq1,dianl1;String response="#00000000000000";private String pcIp;private String pcPort;private int pcport;private Handler handler;InputStream is;InputStreamReader isr;BufferedReader br;private DatagramSocket udpSocket;private ServerSocket tcpServerSocket;private Socket mcuTcpSocket;private InputStream mcuTcpInputStream;private Socket pcTcpSocket;private OutputStream pcTcpOutputStream;protected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);initUI();initChart(turangwenduChart);initChart(turangshiduChart);initChart(huanjingshiduChart);initChart(guangqiangChart);initChart(huanjingwenduChart);initChart(dianliuChart);dbOpenHelper = new MyDBOpenHelper(getApplicationContext(), "SC_Database.db", null, 1);dbWriter = dbOpenHelper.getWritableDatabase();Intent intent = getIntent();Bundle bundle =intent.getExtras();pcIp = bundle.getString("PC_IP");pcPort=bundle.getString("PC_PORT");pcport = Integer.parseInt(pcPort);tcpStart();handler = new Handler() {public void handleMessage(Message msg) {super.handleMessage(msg);switch (msg.what) {case 0:turangwendu.setText(tuwen);turangshidu.setText(tushi);huanjingshidu.setText(huanshi);guangqiang.setText(guangq);huanjingwendu.setText(huanwen);dianliu.setText(dianl);Log.d("Handler", "传感器信息已更新");break;case 1:Toast.makeText(WifiActivity.this, (String) (msg.obj), Toast.LENGTH_SHORT).show();break;}}};mMainHandler = new Handler() {public void handleMessage(Message msg) {switch (msg.what) {case 0: {turangwendu.setText(tuwen);turangshidu.setText(tushi);huanjingshidu.setText(huanshi);guangqiang.setText(guangq);huanjingwendu.setText(huanwen);dianliu.setText(dianl);break;}}}};}public boolean onCreateOptionsMenu(Menu menu) {super.onCreateOptionsMenu(menu);menu.add(1, 1, 1, "设备状态");menu.add(1, 2, 1, "返回");return true;}public boolean onOptionsItemSelected(MenuItem item) {switch (item.getItemId()) {case 1:Intent intent = new Intent();intent.setClass(WifiActivity.this, ControlActivity.class);Bundle bundle = new Bundle();bundle.putString("waizheyang_state", waizheyang_state);bundle.putString("neizheyang_state", neizheyang_state);bundle.putString("dingkaichuang_state", dingkaichuang_state);bundle.putString("cekaichuang_state", cekaichuang_state);bundle.putString("shilian_state", shilian_state);bundle.putString("zhouliufengji_state", zhouliufengji_state);bundle.putString("huanliufengji_state", huanliufengji_state);bundle.putString("wuhua_state", wuhua_state);bundle.putString("guangai_state", guangai_state);intent.putExtras(bundle);startActivity(intent);break;case 2:finish();break;}return super.onOptionsItemSelected(item);}private void initUI() {setContentView(R.layout.activity_wifi);setTitle("温室监控系统");turangwendu = findViewById(R.id.turangwendu);turangshidu = findViewById(R.id.turangshidu);huanjingshidu = findViewById(R.id.huanjingshidu);guangqiang = findViewById(R.id.guangqiang);huanjingwendu = findViewById(R.id.huanjingwendu);dianliu = findViewById(R.id.dianliu);turangwenduChart = findViewById(R.id.turangwenduChart);turangshiduChart = findViewById(R.id.turangshiduChart);huanjingshiduChart = findViewById(R.id.huanjingshiduChart);guangqiangChart = findViewById(R.id.guangqiangChart);huanjingwenduChart = findViewById(R.id.huanjingwenduChart);dianliuChart = findViewById(R.id.dianliuChart);}private void initChart(LineChart chart) {chart.getDescription().setEnabled(false);chart.setTouchEnabled(true);chart.setDragEnabled(true);chart.setScaleEnabled(true);chart.setDrawGridBackground(false);chart.setPinchZoom(true);chart.setDrawBorders(true);chart.setBorderColor(0xA2A2A2);LineData data = http://www.kingceram.com/post/new LineData();chart.setData(data);Legend l = chart.getLegend();l.setForm(Legend.LegendForm.LINE);l.setEnabled(true);XAxis xl = chart.getXAxis();xl.setPosition(XAxis.XAxisPosition.BOTTOM);xl.setDrawLabels(false);xl.setGranularity(1f);xl.setTextColor(Color.WHITE);xl.setDrawGridLines(true);xl.enableGridDashedLine(10f, 10f, 0f);xl.setAvoidFirstLastClipping(true);xl.setEnabled(true);YAxis leftAxis = chart.getAxisLeft();leftAxis.setGranularity(1f);leftAxis.setAxisMaximum(100f);leftAxis.setAxisMinimum(0f);leftAxis.resetAxisMinimum();leftAxis.resetAxisMaximum();leftAxis.setDrawGridLines(true);leftAxis.enableGridDashedLine(10f, 10f, 0f);YAxis rightAxis = chart.getAxisRight();rightAxis.setEnabled(false);}private void addEntry(LineChart chart, String name, String color, float number) {LineData data = chart.getData();if (data != null) {ILineDataSet set = data.getDataSetByIndex(0);if (set == null) {set = createLineDataSet(name, color);data.addDataSet(set);}data.addEntry(new Entry(set.getEntryCount(), number), 0);data.notifyDataChanged();chart.notifyDataSetChanged();chart.setVisibleXRangeMaximum(30);chart.moveViewToX(data.getEntryCount());}}private LineDataSet createLineDataSet(String name, String color) {LineDataSet set = new LineDataSet(null, name);set.setAxisDependency(YAxis.AxisDependency.LEFT);set.setColor(Color.parseColor(color));set.setCircleColor(Color.WHITE);set.setDrawCircles(false);set.setFillAlpha(65);set.setFillColor(ColorTemplate.getHoloBlue());set.setHighLightColor(Color.rgb(244, 117, 117));set.setValueTextColor(Color.WHITE);set.setValueTextSize(9f);set.setDrawValues(false);return set;}private void netDataReceived(char[] temp) {tuwen = new String(temp, 1, 2);tushi = new String(temp, 3, 2);huanwen = new String(temp, 5, 2);huanshi = new String(temp, 7, 2);guangq = new String(temp, 9, 4);dianl = new String(temp, 13, 2);waizheyang_state = new String(temp, 15, 1);neizheyang_state = new String(temp, 16, 1);dingkaichuang_state = new String(temp, 17, 1);cekaichuang_state = new String(temp, 18, 1);shilian_state = new String(temp, 19, 1);zhouliufengji_state = new String(temp, 20, 1);huanliufengji_state = new String(temp, 21, 1);wuhua_state = new String(temp, 22, 1);guangai_state = new String(temp, 23, 1);turangwendu.setText(tuwen);turangshidu.setText(tushi);huanjingshidu.setText(huanshi);guangqiang.setText(guangq);huanjingwendu.setText(huanwen);dianliu.setText(dianl);tuwen1=Integer.parseInt(tuwen);tushi1=Integer.parseInt(tushi);huanshi1=Integer.parseInt(huanshi);guangq1=Integer.parseInt(guangq);huanwen1=Integer.parseInt(huanwen);dianl1=Integer.parseInt(dianl);addEntry(turangwenduChart,"土壤温度", TDS_LINE_COLOR, tuwen1);addEntry(turangshiduChart, "土壤湿度", TEMP_LINE_COLOR, tushi1);addEntry(huanjingshiduChart, "环境湿度", HUM_LINE_COLOR, huanshi1);addEntry(guangqiangChart, "光强", LIGHT_LINE_COLOR, guangq1);addEntry(huanjingwenduChart, "环境温度", TDS_LINE_COLOR, huanwen1);addEntry(dianliuChart, "电流", HUM_LINE_COLOR, dianl1);SQLiteDatabase dbWriter = dbOpenHelper.getReadableDatabase();ContentValues cv = new ContentValues();cv.put("shebeihao", shebei);cv.put("trwendu", tuwen1);cv.put("trshidu", tushi1);cv.put("hwendu", huanwen1);cv.put("hshidu", huanshi1);cv.put("guangq", guangq1);cv.put("dianliu", dianl1);Calendar calendaryzc = Calendar.getInstance();year = calendaryzc.get(Calendar.YEAR);month = calendaryzc.get(Calendar.MONTH)+1;day = calendaryzc.get(Calendar.DAY_OF_MONTH);hour = calendaryzc.get(Calendar.HOUR_OF_DAY);minute = calendaryzc.get(Calendar.MINUTE);second = calendaryzc.get(Calendar.SECOND);shijian=year+"/"+month+"/"+day+""+hour+":"+minute+":"+second;cv.put("shijian", shijian);dbWriter.insert("wenshi", null, cv); }private void sendHandlerMessage(int what, Object msg) {Message message = new Message();message.what = what;message.obj = msg;handler.sendMessage(message);}private void tcpStart() {new Thread(new Runnable() {public void run() {try {socket = new Socket(pcIp, pcport);sendHandlerMessage(1, "连接成功!");pcTcpOutputStream = socket.getOutputStream();isyzc = socket.getInputStream();isrz = new InputStreamReader(isyzc);brx = new BuffereedReader(isrz);new Thread(new Runnable() {public void run() {while (true) {try {response = br.readLine();char[] temp = response.toCharArray();netDataReceived(temp);} catch (Exception e) {e.printStackTrace();}}}}).start();Message msg = Message.obtain();msg.what = 0;mMainHandler.sendMessage(msg);} catch (Exception e) {sendHandlerMessage(1, "连接失败!");e.printStackTrace();}}}).start();}protected void onDestroy() {super.onDestroy();dbWriter.close();}}数据库存储部分public class MyDBOpenHelper extends SQLiteOpenHelper {public MyDBOpenHelper(Context context, String name,SQLiteDatabase.CursorFactory factory, int version) {super(context,name ,factory, version);}public void onCreate(SQLiteDatabase db) {db.execSQL("CREATE TABLE wenshi(" +"device TEXT PRIMARY KEY AUTOINCREMENT," +"trwendu INTEGER," +"trshidu INTEGER," +"hwendu INTEGER," +"hshidu INTEGER," +"guangq INTEGER," +"dianliu INTEGER," +"shijian TEXT);");}public void onUpgrade(SQLiteDatabase _db, int oldVersion, int newVersion) {_db.execSQL("DROP TABLE IF EXISTS wenshishujuku");onCreate(_db);}}public class displaydata extends AppCompatActivity {private SQLiteDatabase dbWriter,dbReader;private MyDBOpenHelper dbOpenHelper;private SimpleCursorAdapter listViewAdapter;private ListView listView;private String currentID="1";protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_displaydata);dbOpenHelper = new MyDBOpenHelper(getApplicationContext(), "SC_Database.db", null, 1);dbReader = dbOpenHelper.getReadableDatabase();dbWriter = dbOpenHelper.getWritableDatabase();showAll();listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {@Overridepublic void onItemClick(AdapterView