1.从和风天气API获取天气数据,解析后通过串口发送到战舰开发板上
2.战舰开发板驱动传感器进行实时天气数据的采集,通过串口传到PC机
感谢机智云物联网开发者社区的帖子,本系统STM32端很短代码参考自这位大神发的帖子:战舰V3通过ESP8266获得网络天气,电脑端Java串口的编写主要参考(下载):使用Java实现串口通信,虽然很多代码都不是我动手写的,但是为了这个课设仍然做了许多努力,希望能记录下来。再次感谢这两位大神!
和风天气API返回的是一个Json字符串比如
{"HeWeather6":[{"basic":{"cid":"CN101010100","location":"北京","parent_city":"北京","admin_area":"北京","cnty":"中国","lat":"39.90498734","lon":"116.4052887","tz":"+8.0"},"update":{"loc":"2018-01-27 16:50","utc":"2018-01-27 08:50"},"status":"ok","daily_forecast":[{"cond_code_d":"101","cond_code_n":"101","cond_txt_d":"多云","cond_txt_n":"多云","date":"2018-01-27","hum":"34","mr":"13:16","ms":"02:41","pcpn":"0.0","pop":"0","pres":"1032","sr":"07:26","ss":"17:28","tmp_max":"-2","tmp_min":"-9","uv_index":"2","vis":"16","wind_deg":"224","wind_dir":"西南风","wind_sc":"微风","wind_spd":"8"},{"cond_code_d":"100","cond_code_n":"100","cond_txt_d":"晴","cond_txt_n":"晴","date":"2018-01-28","hum":"15","mr":"14:05","ms":"03:50","pcpn":"0.0","pop":"0","pres":"1035","sr":"07:25","ss":"17:29","tmp_max":"-1","tmp_min":"-8","uv_index":"2","vis":"20","wind_deg":"350","wind_dir":"北风","wind_sc":"微风","wind_spd":"3"},{"cond_code_d":"100","cond_code_n":"100","cond_txt_d":"晴","cond_txt_n":"晴","date":"2018-01-29","hum":"21","mr":"15:03","ms":"04:57","pcpn":"0.0","pop":"0","pres":"1032","sr":"07:24","ss":"17:31","tmp_max":"1","tmp_min":"-8","uv_index":"2","vis":"20","wind_deg":"259","wind_dir":"西南风","wind_sc":"微风","wind_spd":"4"}],"sunrise_sunset":[{"$ref":"$[0].daily_forecast[0]"},{"$ref":"$[0].daily_forecast[1]"},{"$ref":"$[0].daily_forecast[2]"}]}]}
可以看出,要想获得合适的数据,就必须解析这个Json字符串,通过谷歌可以找到在线格式化Json工具,大概是这个样子的,附传送门
这里我们通过在线格式化只是为了方便下一步的解析,首先,创建一个JSONObject对象
JSONObject json1 = JSONObject.fromObject(sb.toString());
创建JSONArray
JSONArray array1 = json1.getJSONArray("HeWeather6");
用array1中的第一个元素再次创建JSONObject对象
JSONObject json2 = JSONObject.fromObject(array1.getString(0));
创建名为daily_forecast的JSONArray
JSONArray array2 = json2.getJSONArray("daily_forecast");
输出最近三天的部分天气数据
for(int i = 0;i < array2.size();i++){
//System.out.println(array2.getString(i));
String string3 = array2.getString(i);
JSONObject json3 = JSONObject.fromObject(string3);
System.out.print("时间:"+json3.getString("date")+" ");
System.out.print("最低温度:"+json3.getString("tmp_min")+" ");
System.out.print("最高温度:"+json3.getString("tmp_max")+" ");
System.out.print("天气:"+json3.getString("cond_txt_d")+" ");
System.out.println("湿度:"+json3.getString("hum"));
}
控制台输出
时间:2018-01-27 最低温度:-8 最高温度:-2 天气:晴间多云 湿度:34
时间:2018-01-28 最低温度:-9 最高温度:-1 天气:晴 湿度:15
时间:2018-01-29 最低温度:-8 最高温度:1 天气:晴 湿度:21
我的解析Json思路很简单,不断创建JSONObject和JSONArray对象,层层解析,最后得到需要的数据,点击Json格式大神讲解。
首先我们要知道,Java编写串口工具串口发送数据的类型都是byte[],这样我们就只需要把要发送的数据变成byte[]类型即可啦,
WeatherData weatherDataHF = new WeatherData("key=db3e861fc7654111800271e316414820&location="+cityName.toString(),
"https://free-api.heweather.com/s6/weather/forecast?parameters");
接下来似乎只需要把这些数据通过getBytes()方法转化就可以了但是我们仔细回想一下之前得到的数据,有没有什么不对劲?没错!串口不能发送汉字!!!所以这里就需要对数据进行处理,转化成数字或者字符串,这学期学习了计算机体系结构,所以我参考了一下查表法,把天气转换成特定的数字组合,如晴天为001,阴天为010,温度也用三位数字表示,第一位数字为0则表示高于0℃,为1则表示低于0℃,如最低温度-1℃表示为101。OK,第一个问题解决了。
兴冲冲的去测试串口数据发送,但是发送的数据没有显示什么鬼,奇怪的每次发送之后数据并没有传输,但是使用串口发送助手之后点第一下马上有了结果,翻了翻战舰的串口接收代码,
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中断(接收到的数据必须是0x0d 0x0a结尾)
接收中断必须是ox0d 0x0a结尾!所以需要把数据以\r\n结尾,
StringBuilder weatherData = new StringBuilder();
weatherData.delete(0, weatherData.length());
weatherData.append(weatherDataHF.getWeatherData());
byte[] order = weatherData.toString().getBytes();
SerialTool.sendToPort(serialPort, order);
请忽略我清奇的脑回路代码,Java初学者伤不起。
这次课程设计总的来说很多代码都是从网上复制粘贴,但是也还是遇到了不少问题然后大体解决了,尚未解决的问题有:
PC端的UI界面有时会崩溃,猜测是数据传送太快出现溢出
战舰端的数据发送需要高于一定的频率不断发送,不然PC端接收不到数据,猜测是软件问题,串口助手可以正常工作
基于STM32与和风天气API的交互系统
注:战舰开发板需要dht11温湿度传感器,没有传感器也可以在keil文件中注释掉相关初始化调用函数。