室内定位可以应用在很多场景,由于受到室内环境的限制,GPS信号无法有效的接收,这时可以利用室内的WIFI热点提供的信号强度来进行辅助定位。通常在室内都会有很多的WIFI热点,我们可以把室内的区域划分为多个网格,在每一个网格测量所接收到的WIFI热点的信号强度,根据这些信息来建立一个WIFI信号指纹库,以后我们就可以通过比对指纹库,来确定在室内的位置了。
手机APP测量WIFI信号
首先我们先编写一个APP,用于测量WIFI的信号强度并且上报给服务器保存。这里我采用了HBuilderX来编写,这个HBuilderX采用了HTML 5+的技术,可以快速的用我熟悉的网页+JS的方式来写Android和IOS的应用。
新建一个HbuilderX的项目,在目录下新建一个index.html文件,内容如下:
输入室内网格编号:
Device Orientation: -->BSSID Level
这里用到了plus.android来调用android的原生方法,例如通过调用WifiManager来对WIFI信号进行扫描,把扫描结果的BSSID和信号强度保存下来。另外HTML5的规范支持获取设备的方向信息,以0-360度来表示设备的朝向,因为设备指向不同的方向也会影响信号的强度,因此也需要记录这个信息。最后当点击开始扫描这个按钮的时候,就会把这些信息提交到后台的服务器,记录到数据库中。
要支持WIFI扫描,还需要在manifest.json文件里面设置相应的权限,按照Android文档的说法,Android 10及以上的版本还需要开启ACCESS_FINE_LOCATION,ACCESS_WIFI_STATE,CHANGE_WIFI_STATE的权限,以及设备需要启用位置信息服务。另外Android默认会对startScan有节流限制,即一定时间内限制调用的次数,可以在开发者选项->网络->WIFI扫描调节下进行关闭,取消限制。
以下是这个APP运行的效果:
WIFI测量APP
后台应用记录WIFI测量数据
编写一个后台应用,暴露一个API接口,用于接收APP上报的WIFI测量数据。
这里采用springboot+JPA+Postgresql的架构。
在start.spring.io网站里面新建一个应用,artifact名字为wifiposition,依赖里面选择spring web, JPA,打开应用,在里面新建一个名为WifiData的Entity类,代码如下:
package cn.roygao.wifiposition;import java.util.Date;import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.Type;
import org.hibernate.annotations.TypeDef;import com.alibaba.fastjson.JSONArray;
import com.vladmihalcea.hibernate.type.json.JsonBinaryType;@Entity
@TypeDef(name = "jsonb", typeClass = JsonBinaryType.class)
@Table(name = "wifidata")
public class WifiData {@Id@GeneratedValue(strategy=GenerationType.AUTO)private Long id;private String gridId;private Float orientation;@Type(type = "jsonb")@Column (name="measurement", nullable = true, columnDefinition = "jsonb")private JSONArray measureArray;@CreationTimestampprivate Date createdTime;public WifiData() {}public WifiData(String gridId, Float orientation, JSONArray measureArray) {this.gridId = gridId;this.orientation = orientation;this.measureArray = measureArray;}public Long getId() {return this.id;}public void setId(Long id) {this.id = id;}public String getGridId() {return this.gridId;}public void setGridId(String gridId) {this.gridId = gridId;}public Float getOrientation() {return this.orientation;}public void setOrientation(Float orientation) {this.orientation = orientation;}public JSONArray getMeasureArray() {return this.measureArray;}public void setMeasureArray(JSONArray measureArray) {this.measureArray = measureArray;}
}
这个代码里面会保存measurement的JSON数组到PG的JSONB格式的数据列里面,因为hibernate默认没有提供这种类型,这里引入了com.vladmihalcea.hibernate.type.json.JsonBinaryType来提供支持。
在pom.xml里面需要添加以下的依赖:
com.vladmihalcea hibernate-types-52 2.3.4
新建一个名为WifiRepository的接口类,代码如下:
package cn.roygao.wifiposition;import org.springframework.data.repository.CrudRepository;public interface WifiDataRepository extends CrudRepository{}
新建一个名为WifiController的类,实现HTTP接口,代码如下:
package cn.roygao.wifiposition;import java.util.logging.Logger;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;@RestController
public class WifiController {@Autowiredprivate WifiDataRepository repository;private final static Logger LOGGER = Logger.getLogger(WifiController.class.getName());@PostMapping("/senddata")public ResponseEntity sendData(@RequestBody JSONObject data) {Float orientation = data.getFloat("Orientation");String gridId = data.getString("GridId");JSONArray wifiSignal = data.getJSONArray("WifiSignal");repository.save(new WifiData(gridId, orientation, wifiSignal));return ResponseEntity.accepted().body("OK");}
}
在application.properties里面增加postgres的相关配置,如下:
spring.datasource.url= jdbc:postgresql://localhost:5432/wifidb
spring.datasource.username= postgres
spring.datasource.password= postgresspring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation= true
spring.jpa.properties.hibernate.dialect= org.hibernate.dialect.PostgreSQLDialect# Hibernate ddl auto (create, create-drop, validate, update)
spring.jpa.hibernate.ddl-auto= update
运行./mvnw clean install进行编译打包,然后运行即可。