WIFI室内定位系统设计与实现(小学期满分项目)

WIFI Positioning Software Design Manual(WIFI室内定位软件设计说明书)

作为在CSDN上发的第一篇,稍微介绍一下吧,这个是我在小学期做的一个拿到了A(满分)的项目,是利用wifi信号的强弱进行室内的定位,这个是当时写的一个软件设计说明书,比较详细,大家可以通过目录来看想看的内容
然后这里是算法讲解视频:

添加链接描述

这个是当时去实验的视频:
添加链接描述

文章目录


Software Designed by group 1,2020-0712

1.Abstract(摘要)

Application scenario: This product takes the 3rd floor of Yifu as an example, and faces the campus network coverage area to find corresponding locations.
Product features: precise navigation and positioning in the building, recommended hot search, recommended location, evaluation.
Target users: school teachers and students, administrative staff, school workers, outside school staff

应用场景:本产品以逸夫3层为例,面向校园网覆盖区域,查找相应地点。
产品特色:楼内精准导航定位,推荐热搜,推荐地点,评价。
目标用户:在校师生,行政人员,校工,校外人员

2.Preface(引言)

2.1 Project research background and significance(项目研究背景及意义)

Product positioning: This product is a modern, functional app that provides users with services such as indoor map display, indoor destination navigation, location detailed information query, fault reminder, and absence judgment in class.
Product features: The product has a beautiful interface and is easy to use. In addition to the basic positioning and navigation and information query functions, it also provides users with special services such as fault reminders and class registration to meet the needs of users.
User needs: There are many classrooms and other places in the teaching building, and the information in the classroom is unknown. Students need an app that can quickly navigate to the destination and obtain detailed classroom information to save time and achieve results; for teachers, provide teachers with judgment students The service of whether to attend class or leave the classroom halfway, to meet the teacher’s need to obtain student information.

产品定位:该产品是面向广大学生、教师,可为用户提供室内地图展示、室内目的地导航、地点详细信息查询、故障提醒、课上缺席判断等服务的一款现代型、功能型app。
产品特色:该产品界面美观、使用方便,除了基础的定位导航、信息查询功能外,还为用户提供故障提醒、上课签到等特色服务,满足用户多方面需求。
用户需求:教学楼内教室等地点较多,且教室内信息未知,学生需要一款可快速导航去目的地和获取教室详细信息的app以节约时间、达到效果;面向老师,为老师提供判断学生是否上课、中途离开教室的服务,满足老师的获取学生信息需求。

2.2 Related products and comparison(相关产品以及对比)

  • Compared with software for social environment(e.g. DaZhongDianPing)
    与面向社会环境的软件相比(例如:大众点评)

Element recommend part is similar to them, the app will recommend the elements nearby according to user’s position. And the elements here include things like “CAFE” “Classroom” “Computer Room”.
But because of school environment, it does not have that much kinds of element.
But our advantage (or distinguishing feature) is our app faces to Campus.
元素推荐部分与此类似,应用程序将根据用户的位置推荐附近的元素。 这里的元素包括“ CAFE”,“教室”,“计算机室”之类的东西。
但是由于学校环境的原因,它没有太多种类的元素。
但是我们的优势(独特功能)是我们的应用程序面向大学校园。

  • Compared with software for school environment(e.g. JiaoDaMoHe)
    与面向学校环境的软件相比(例如:交大魔盒)

Compare to this app, our advantages are:
First, it does not has positioning function, our app add the positioning function. And functions based on positioning such as nearby elements recommend.
相比这个程序,我们的优势是:
首先,它没有定位功能,我们的应用程序添加了定位功能。 并推荐基于定位的功能,例如附近的元素。

扫描二维码关注公众号,回复: 12044715 查看本文章

2.3 Value Of the project and Innovation (项目价值及创新)

Today’s university campuses are often very large, and every teaching building is like a labyrinth. If it is not a student of this school or a student who does not come to a place often, it may get lost. In addition, there is no specific location information on campus on the positioning software used by the public (such as Amap), let alone detailed information such as classrooms in the building, so our campus-based wifi positioning system based on campus network is Will play a vital role.
Plus some additional features, such as nearby recommendations, I can choose to go to the nearest study room, computer room. Or, if you are in a hurry, you can find the nearest toilet (this is very important). Or sign in the classroom, the attendance of this university classroom will be much more convenient.
现在的大学校园往往面积往往非常大,每个教学楼里都如迷宫一般,如果不是本校学生或者是不经常来某地的同学可能会迷路。再加上大众使用的定位软件(如高德地图)上是没有校园内具体地点信息的,更别说楼内教室等详细信息了,所以我们这款面向校园的基于校园网的wifi定位系统就会起到至关重要的作用。
再加上一些附加功能,比如附近推荐,我可以选择去到最近的自习室,计算机房。或者,有的时候着急,可以找到最近的厕所(这个很重要哦 )。或者说课堂签到,这个大学课堂的考勤就会方便很多。


3.Design Plan (开发计划)

Time schedule

Mon 02 Mon 09 Requirements Analysis basic UI design UI beautify UI design(coding) Client and Server(network) DataBase User system Position Element recommend Information query Feedback Check Presence MalFunction Remind Finish the Document PPT R-A D-D B-F E-P END Gantt Diagram
  • 1. Requirement analysis
  • 2. basic UI design
  • 3. UI beautify
  • 4. UI design(coding)
  • 5. Client and Server(network)
  • 6. DataBase
  • 7. Position
  • 8. Element recommend
  • 9. Information query
  • 10. Feedback
  • 11. Check Presence
  • 12. MalFunction Remind
  • 13. PPT
  • 14. Document
In short Meaning
R-A Requirements Analysis
D-D Demo Design
B-F Basic Function
E-P Extra Part
END end of the task(including the file and ppt)

Basic functions

  1. UI design
  2. User system
  3. Position
  4. Network

Extra functions

  1. Element recommend
  2. Location information query
  3. Feedbacks
  4. Malfunction remind
  5. Check presenece in class
  6. UI beautify

Distribute

Work Manager Task Explain
Requirement analysis LiuJiaXu
Basic UI design Liujiaxu using modao
UI beautify Liujiaxu coding
UI design(coding) Liujiaxu coding
Client and Server(network) Zhangfu
Position ZQK
Element recommend huanglin 附近4个不同TAG类ROOM
Information query helanlan 输入房间ID,返回information
Feedback LiuJiaXu 房间页面,评论区
Check Presence ZQK
MalFunction Remind Hemaoxin 获取当前位置p0,向服务器发送新位置
PPT huanglin
Document ZQK

Information:
1.id
2.name
3.TAG: ROOM=CAFE? CLASSROOM? WC? COMPUTER ROOM?
4.PICTURE
5.FEEDBACKS

Manager is the man who manage the corresponding part, not the one who is going to write the whole code, but the one who is going to be the leader to lead the team to complete the task.

4.Feasibility Analysis (可行性分析)

4.1 Market feasibility analysis (市场可行性分析)

  • As the indoor space for people’s activities becomes larger and more complex, points of interest (POI) become more and more abundant. Demand for positioning and guiding services for large indoor activity venues such as shopping malls, airports, and teaching buildings is increasing. It is this demand that has brought huge market opportunities for the indoor positioning system (IPS). The indoor positioning of this project is based on the wifi signal strength. The improved KNN algorithm has high positioning accuracy and is mainly targeted at the student group. It has strong pertinence, more detailed application development, and better user experience. Therefore, the project is bound to open up a market.
    随着人们活动的室内空间越来越庞大和复杂,兴趣点(POI)越来越丰富。商城,机场,教学楼等大型室内活动场所的定位和引导服务需求日趋强烈。正是这种需求,为室内定位系统(IPS,Indoor Positioning System)带来了巨大的市场机会。本项目的室内定位基于wifi信号强度进行定位,改良后的KNN算法定位精度高,且主要面向学生群体,针对性强,应用拓展更为细致,用户体验更佳。因此,该项目势必能开拓出一片市场。

4.2 Technical feasibility analysis (技术可行性分析)

  • The indoor positioning system is different from the outdoor GPS positioning. The indoor positioning requires higher precision, and the positioning accuracy error is allowed within 1.5meters. By collecting WiFi signal strength, using KNN algorithm (K-NearestNeighbor algorithm), multi-directional comparison of signal strength in the database, you can accurately know the current indoor location. Therefore, technically, the project is completely feasible.
    室内定位系统不同于室外的GPS定位,室内定位对精度的要求更高,定位精确度误差允许范围在1.5米之内。通过采集WiFi信号强度,使用KNN算法(K-NearestNeighbor algorithm),多方位比对数据库中的信号强度,便可精确获知当前的室内定位。因此,在技术上,该项目是完全可行的。

5. Requirements Analysis (需求分析)

5.1 Functional requirements (功能性需求)

5.1.1 Functional block diagram (功能模块结构图)

digraph hierarchy {
  nodesep=1.0 // Increases the separation between nodes

  node [color=Red,fontname=Courier,shape=box] // All nodes will this shape and colour
  edge [color=Purple, style=dashed] // All the lines look like this
  WIFIPositioning->{Extra_Part}
  Extra_Part->{Element_Recommend InformationQuery Malfunction_Remind FeedBack}
  
}

5.1.2 Core function module description (核心功能模块描述)

  • Basic functions
  1. UI design
  2. User system
  3. Position
  4. Network
  • Extra functions
  1. Element recommend
    Regarding element recommend, the system will recommend some elements near the user, such as cafes, shops, study rooms, computer rooms, etc.
    关于元素推荐,系统将推荐用户附近的一些元素,例如咖啡馆,商店,书房,计算机室等。

  2. Location information query
    For location information query, we provide a series of location information query for each classroom, teaching building, cafe, etc. Location information includes location information and navigation route, pictures of the place (uploaded by the user or brought by the system), comments on the place Wait.
    对于位置信息查询,我们为每个教室,教学楼,咖啡馆等提供一系列位置信息查询。位置信息包括位置信息和导航路线,该地点的图片(由用户上传或由系统带来),评论 在这个地方等等。

  3. Feedbacks
    User feedback on the location, for example, the classroom is sunny and the room is dim, or there is no outlet or outlet in a classroom. Drinks in this cafe are very good, but the boss has a bad service attitude.
    In order to give users more opportunities for reference and vomiting.
    用户对位置的反馈,例如,教室晴朗,房间昏暗,或者教室中没有插座。 这家咖啡馆的饮料很好,但老板的服务态度很差。
    为了给用户更多的参考和吐槽机会。

  4. Malfunction remind
    Failure repair, this function can provide better repair service for teachers and students in the school. After clicking to report the current location, the system will automatically read the current location (as long as it is within the coverage of the campus network), and notify the nearby staff to deal with it.
    故障修复,此功能可以为学校的师生提供更好的修复服务。 单击以报告当前位置后,系统将自动读取当前位置(只要它在校园网络的范围内),并通知附近的员工进行处理。

  5. Check presenece in class
    The classroom sign-in system can be considered for docking with the school student management information system to achieve classroom attendance. The system can record when and where the student stays, how long he stays, after importing the student schedule and real-time leave, we can use this to record whether the student is late, leaving early, or absent from class
    可以考虑将教室登录系统与学校学生管理信息系统对接以实现教室出勤。 该系统可以记录学生的时间和地点,停留的时间,导入学生的日程安排和实时休假后,我们可以使用它来记录学生是否迟到,早退或缺课

5.2 Non-functional requirements (非功能性需求)

  1. performance requirements:
    Response time: divided into daily interaction class, daily query class. The daily interaction has the system to provide the peripheral recommendation for the user automatically, the classroom comment and so on, the daily interaction class business has the higher response request. Query business such as study room inquiries, around the location inquiries, classroom check-in inquiries and so on. Because the query business is affected by the complexity of the query, the size of the query data and other factors, it needs to be determined according to the specific situation, and give a reference range. Response time indicators include: average response time reference (seconds), peak response time reference (seconds).
    Number of users: Number of users to consider the increase in the number of users long case, there are the following indicators: total number of users, peak online users, peak concurrent users, average online users, average concurrent users.
    throughput: estimation of system query volume. The indicators are positioning success (pen/year), peak evaluation (days/day).
    Data storage: Annual data storage capacity (G) and the expected (growth) value of that amount in the coming years. Indicators include cumulative storage capacity (G), annual growth (G).
    性能需求:
    响应时间:分日常交互类、日常查询类。日常交互有系统自动为用户提供周边推荐,教室点评等,日常交互类业务具有较高的响应要求。 查询类业务如自习室查询、周围地点查询,课堂签到查询等。查询业务由于受到查询的复杂程度、查询的数据量大小等因素的影响,需要根据具体情况而定,给出一个参考范围。响应时间指标包括:平均响应时间参考值(秒)、峰值响应时间参考值(秒)。
    用户数:用户数要考虑用户数的增长情况,有以下指标:总用户数、峰值在线用户数、峰值并发用户数、平均在线用户数、平均并发用户数。
    吞吐量:系统查询量的估算。指标有定位成功(笔/年)、高峰期评价(个/天)。
    数据存储量:每年的数据存储容量(G)及未来几年该数量的预期(增长)值。指标包括累计存储容量(G)、年增长(G)。

  2. system reliability:
    Positioning operations should be available during all working days from Monday to Sunday; other operations should meet 7×24 small Android4.0 above
    系统可靠性:定位业务应在从星期一到星期日的所有工作日的工作时间是可以使用的;其它业务应满足7×24小时可以使用;Android4.0以上

  3. scalability:
    load balancing can be achieved; if the amount of information in the future, the system can increase the server to achieve expansion. The interface is humanized and the operation is easier.
    可扩展性:可实现负载均衡;日后若信息量较大,则系统可相应增加服务器实现扩展。界面人性化,操作更简易。

5.3 Use case diagram (用例图)

6. Outline design (概要设计)

6.1 System architecture design (系统架构设计)

digraph hierarchy {
  nodesep=1.0 // Increases the separation between nodes

  node [color=Red,fontname=Courier,shape=box] // All nodes will this shape and colour
  edge [color=Purple, style=dashed] // All the lines look like this

  School_WiFi_Positioning->{Basic_Functions Extra_Part}
  Basic_Functions->{User_System Positioning Service_Based_On_Positioning}
  Extra_Part->{}
  
}
digraph hierarchy {
  nodesep=1.0 // Increases the separation between nodes

  node [color=Red,fontname=Courier,shape=box] // All nodes will this shape and colour
  edge [color=Purple, style=dashed] // All the lines look like this

  Extra_Part->{Element_Recommend InformationQuery Malfunction_Remind FeedBack}
  
}

6.2 System total functional structure design (系统总功能结构设计)

User System

There are three parts:

  • Log in:
  • Register:
  • Modify:

Positioning

It is divided into two parts:

  • wifi scan part
  • positioning algorithem

Element Recommend

It includes:

  • get your current Position
  • get 4 different type of room which is the nearest

Information Query

It includes two parts:

  • interface jump
  • information display algorithem

Malfunction Remind

It includes one part:

  • Send to server

Comment

This part is in room information:

  • Receive
  • Display

6.3 Key technical design (关键技术设计)

User System

  1. Connection mode:
  • Using java Socket class to connect clients and server
  • Clients need to confirm server’s ip address and serve port
  1. TCP protocol:

User information transmission
[color=red]

Register
[color=#907bf7]

direction Message type
client->server “R” + # + “name” + # + “password”
server->client “YR” + # + “id”
server->client “NR” + # + “Name already exists”

[color=red]

Log in
[color=#907bf7]

direction Message type
client->server “L” + # + “id” + # + “password”
server->client “YL” + # + “id” + # + “password” + # + “name” + # + “number” + # + “personality”
server->client “NL” + # + “user id doesn’t exist”
server->client “NL” + # + “password is wrong”

[color=red]

Modify information
[color=#907bf7]

direction Message type
client->server “M1” + # + “new password”
client->server “M2” + # + “new name” + # + “new number” + # + “new personality”
client->server “M3”
client->server “picture”
server->client “YM1” + # + “password”
server->client “NM1” + # + “Something error”
server->client “YM2” + # + “name” + # + “number” + # + “personality”
server->client “NM2” + # + “Something error”
server->client “YM3”
server->client “NM3” + # + “Something error”

Position query
[color=red]

Basic information
[color=#907bf7]

direction Message type
client->server “Q” + # + “room id”
server->client “YQ” + # + “No feedback”
server->client “YQ” + # + “name” + # + “feedback”
server->client “NQ” + # + “Query failed”

[color=red]

Add feedback
[color=#907bf7]

direction Message type
client->server “F” + # + “room id” + # + “user name” + # + “feedback”
server->client “YF”
server->client “NF” + # + “Something error”

[color=red]

Malfunction remind
[color=#907bf7]

direction Message type
client->server “E” + # + “room id” + # + “explain”
  1. Server:
  • Listen for connection requests
  • Get data from SQLite database instantly
  • Use “synchronized” keyword to handle thread
  1. Client:
  • Using correct ip address and serve port to connect with server
  • Create a new thread to continuously receive the message sent by server
  • Pack the message received in the thread and pass it into an instance of Handler class
  • Using instance of Handler class to manage and update UI

WIFI SIGNAL SCAN

First we get the permission by from system
this code in AndroidManifest.xml

<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"></uses-permission>
    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"></uses-permission>
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"></uses-permission>
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"></uses-permission>
    <uses-permission android:name="android.permission.INTERNET"></uses-permission>

But it is not enough in some vertion of android, so we need to ask for it.

private int location_request_code = 100;
private void checkPermission() {
        String[] REQUEST_PERMISSIONS = {android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.CHANGE_WIFI_STATE, Manifest.permission.ACCESS_WIFI_STATE};
        int LocPermission = ContextCompat.checkSelfPermission(this, REQUEST_PERMISSIONS[0]);
        int AccPermission = ContextCompat.checkSelfPermission(this, REQUEST_PERMISSIONS[1]);
        int ChPermission = ContextCompat.checkSelfPermission(this, REQUEST_PERMISSIONS[1]);
        if (LocPermission != PackageManager.PERMISSION_GRANTED || AccPermission != PackageManager.PERMISSION_GRANTED || ChPermission != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, REQUEST_PERMISSIONS, location_request_code);
        }
        Log.d("mark", "The permissions has been satisfied");
    }

Then we are going to use the WIFIManager to do the remaining.
So we should use the baseContext to init the WIFIManager

final Context context = getBaseContext();
wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);

Then use the BroadCastReceiver to start

final BroadcastReceiver wifiScanReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                boolean success = intent.getBooleanExtra(WifiManager.EXTRA_RESULTS_UPDATED, false);
                if (success) {
                    scanResultList = scanSuccess();
                } else {
                    scanFailed();
                }
            }
        };

And u can get a list that recorded the ScanResult

private List<ScanResult> scanSuccess() {
        msg+=("\nSCAN SUCCESS\n");
        List<ScanResult> scanResultList = wifiManager.getScanResults();
        Iterator<ScanResult> itr = scanResultList.iterator();
        while (itr.hasNext()) {
            ScanResult result = itr.next();
            msg+=("\n"+result.BSSID+","+result.SSID+","+result.level+"\n");
        }
        return scanResultList;
    }

    private void scanFailed() {
        msg+=("\nSCAN FAILED\n");
    }

Positioning

For starters, I should tell you three maps which has different dimension.
First map is the 2-d map, that is the map which is going to display.

Second map is the 1-d map, that is the map which shows the correspondence between real room and roomID

Third map is the 4-d map, which record the strongest 4 AP information of each room.

Secondly, I am going to introduce 4 classes

  1. AP class
    This class represent the Access Points, it is our core value of positioning.
  2. Point class
    This class represent the Position Point, it has the coordinate value of every map(4-d map, 1-d map, 2-d map)
  3. Map class
    This is our 4-d map
  4. Positioning class
    This class include the major positioning algorithm

You can get your position by two calculate methods, by DIS or by COS. But the basic algorithm is similar.

You are going to use the function:

//major positioning code
    public int getMyPositionByDis(Point cPosition, Context context)
    {
    }

    public int getMyPositionByCos(Point cPosition, Context context)
    {
    }

And it will call this function to find the nearest point in map

private Point findTheNearestPointByDis(Point currentPositionPoint, final Context context)
    {
        
    }

And this is the calculate function:

// calculate the Euclidean Distance
    private double calculateDis(Point p1, Point p2)
    {
        
    }
// calculate the cosine in 4-dimensional map
    private double calculateCos(Point p1, Point p2)
    {
    }

    // calculate the inner product
    private double calculateInnerProduct(Point p1, Point p2) {
       
    }

And if you read the code carefully, or think about the algorithm carefully, you will find a function called coordinate correction. This is necessary before we calculate the distance in 4-d map for the reason that there are too many APs in the map, so two point which is goint to calculate must be in the same coordinate. If it cannot find the corresponding AP, that means the current point is too far from the point in Map, so we assign a null AP as the AP in the new coordinate corrected point.

public Point correctCoordinate(Point pInMap, Point currentPosition)
    {
        
    }

Element Recommend

It will recommend 4 nearest room which has different tags.

Information Query

  1. UI design
  • using the tools of the android studio to design the interface: the listview interface and the detailed interface
  1. interface jump
  • when the search button is clicked, it gets the key number of the searchText and turn to the listview
  • press the item of the listview, it turns to the interface of the single room which shows the detailed information
  1. information display algorithem
  • first, getting the num of the searchText and passing it to the SearchActivity. Find the rooms which contains the num, and show them on the listview interface.
  • then, get the roomID of the clicked item and passing it to RoomInfoActivity, the class will get the TagName and RoomName by the roomID. These information will show on the detailed interface.

Malfunction Remind

Comment

  1. Server:
  • Design methods to update comments based on the TCP protocol
  1. Client:
  • Design UI to meet user and transmission needs
  • Design event response to upload comment to server database

Others

  1. the Study, Office, Other, All button
  • the button clicked function is in the MenuActivity, when the button is clicked, turns to listview interface. The respective information of these buttons is stored in each activity and the information will show on the listview.
  • when the item is clicked, it turns to the detailed interface and pass the roomId to the RoomInfoActivity, the class will get the TagName and RoomName by the roomID. These information will show on the detailed interface.

6.4 DataBase design (数据库设计)

Server Database Design:

  1. UserInfo table:
digraph hierarchy {
  nodesep=1.0 // Increases the separation between nodes

  node [color=Red,fontname=Courier,shape=box] // All nodes will this shape and colour
  edge [color=Purple, style=dashed] // All the lines look like this

  User->{ID Name password phone_number personality}
  
}
  1. Comment table:
    (Different position has different table to store the information of comment)
digraph hierarchy {
  nodesep=1.0 // Increases the separation between nodes

  node [color=Red,fontname=Courier,shape=box] // All nodes will this shape and colour
  edge [color=Purple, style=dashed] // All the lines look like this

  Feedback->{user_name position_name comments}
  
}
  1. 4-Dimensional Map
Id AP Name BSSID SSID level1 level2 level3 average level
1 AP1 0e:69:6c:d6:a2:f7 web.wlan.bjtu -58 -58 -52 -56
1 AP2 16:69:6c:d6:a2:f7 local.wlan.bjtu -59 -59 -54 -57
1 AP3 0a:69:6c:d6:a2:f7 eduroam -59 -59 -53 -57
1 AP4 0a:69:6c:d6:8d:98 eduroam -59 -59 - -59
2 AP1 12:69:6c:d6:8d:97 phone.wlan.bjtu -44 - - -44
2 AP2 16:69:6c:d6:8d:97 local.wlan.bjtu -46 -53 - -50
2 AP3 0e:69:6c:d6:8d:97 web.wlan.bjtu -46 -53 - -50
2 AP4 1a:69:6c:d6:8d:97 NULL -46 - - -46
3 AP1 1a:69:6c:bb:23:04 NULL -35 -39 -39 -38
3 AP2 16:69:6c:bb:23:04 local.wlan.bjtu -37 - -38 -38
3 AP3 0a:69:6c:bb:23:04 eduroam -37 - -38 -38
3 AP4 0e:69:6c:b9:71:9d web.wlan.bjtu -37 -37 - -37
4 AP1 1a:69:6c:d6:9c:bb NULL -58 - - -58
4 AP2 16:69:6c:d6:9c:bb local.wlan.bjtu -59 -53 -54 -55
4 AP3 12:69:6c:d6:a3:03 phone.wlan.bjtu -59 -53 -53 -55
4 AP4 0a:69:6c:d6:9c:bb eduroam -60 -54 -54 -56
5 AP1 0e:69:6c:d6:8f:17 web.wlan.bjtu -51 -52 -49 -52
5 AP2 12:69:6c:d6:8f:17 phone.wlan.bjtu -51 -52 -49 -52
5 AP3 1a:69:6c:d6:8f:17 NULL -51 -53 - -52
5 AP4 16:69:6c:d6:8f:17 local.wlan.bjtu -52 -52 -49 -51
6 AP1 0e:69:6c:d3:40:8e web.wlan.bjtu -31 -32 - -32
6 AP2 0a:69:6c:d3:40:8e eduroam -31 -32 - -32
6 AP3 1a:69:6c:d3:40:8e NULL -32 -32 - -32
6 AP4 12:69:6c:d3:40:8e phone.wlan.bjtu -32 -33 - -33
7 AP1 0e:69:6c:bb:87:fb web.wlan.bjtu -54 -54 -54 -54
7 AP2 1a:69:6c:bb:87:fb NULL -54 -54 -54 -54
7 AP3 12:69:6c:bb:87:fb phone.wlan.bjtu -54 -54 -54 -54
7 AP4 16:69:6c:bb:87:fb local.wlan.bjtu -54 -54 -54 -54
8 AP1 16:69:6c:d4:47:f6 local.wlan.bjtu -50 -50 -49 -50
8 AP2 1a:69:6c:d4:47:f6 NULL -52 -52 - -52
8 AP3 12:69:6c:d4:47:f6 phone.wlan.bjtu -52 -52 -50 -51
8 AP4 0e:69:6c:d4:47:f6 web.wlan.bjtu -52 -52 - -52
9 AP1 16:69:6c:d6:a3:03 local.wlan.bjtu -50 -36 -57 -48
9 AP2 0e:69:6c:d6:a3:03 web.wlan.bjtu -50 -37 -58 -48
9 AP3 12:69:6c:d6:a3:03 phone.wlan.bjtu -51 -66 -58 -58
9 AP4 0a:69:6c:d6:a3:03 eduroam -53 -36 -58 -49
10 AP1 12:69:6c:b9:71:9d phone.wlan.bjtu -62 -62 -61 -62
10 AP2 1a:69:6c:b9:71:9d NULL -62 -62 -61 -62
10 AP3 0a:69:6c:b9:71:9d enduroam -62 -62 -61 -62
10 AP4 16:69:6c:b9:71:9d local.wlan.bjtu -62 -62 -61 -62
12 AP1 1a:69:6c:d6:a5:2f NULL - -39 -39 -39
12 AP2 12:69:6c:d6:a5:2f phone.wlan.bjtu - -39 -39 -39
12 AP3 0a:69:6c:d6:a5:2f eduroam - -40 -40 -40
12 AP4 0e:69:6c:d6:a5:2f web.wlan.bjtu - -40 -40 -40
13 AP1 16:69:6c:d6:a3:7b local.wlan.bjtu -43 - - -43
13 AP2 16:69:6c:d6:a2:f7 local.wlan.bjtu -48 - - -48
13 AP3 0a:69:6c:d6:a2:f7 eduroam -48 - - -48
13 AP4 12:69:6c:d6:a2:f7 phone.wlan.bjtu -48 - - -48
14 AP1 16:69:6c:d3:25:7a local.wlan.bjtu -52 -49 - -51
14 AP2 0a:69:6c:d3:25:7a eduroam -52 -49 - -51
14 AP3 16:69:6c:b9:70:d7 local.wlan.bjtu -53 - - -53
14 AP4 12:69:6c:d3:25:7a phone.wlan.bjtu -53 - - -53
15 AP1 0a:69:6c:d6:91:27 eduroam -47 -40 -36 -41
15 AP2 16:69:6c:d6:91:27 local.wlan.bjtu -48 -39 -36 -41
15 AP3 1a:69:6c:d6:91:27 NULL -48 -38 -36 -41
15 AP4 12:69:6C:d6:91:27 phone.wlan.bjtu -48 -38 -36 -41
16 AP1 1a:69:6c:d4:39:e6 NULL -35 -30 - -33
16 AP2 16:69:6c:d4:39:e6 local.wlan.bjtu -36 -30 - -33
16 AP3 0a:69:6c:d4:39:e6 eduroam -36 -31 - -34
16 AP4 0e:69:6c:d4:39:e6 web.wlan.bjtu -36 -30 - -33
17 AP1 0e:69:6c:d3:6d:77 web.wlan.bjtu -61 -61 -62 -61
17 AP2 12:69:6c:d3:6d:77 phone.wlan.bjtu -61 -61 -62 -61
17 AP3 0a:69:6c:d3:6d:77 eduroam -61 -61 - -61
17 AP4 16:69:6c:d3:6d:77 local.wlan.bjtu -62 -62 -66 -63
18 AP1 16:69:6c:d6:91:27 local.wlan.bjtu -42 -66 -59 -56
18 AP2 1a:69:6c:d6:91:27 NULL -42 -65 -58 -55
18 AP3 12:69:6c:d6:91:27 phone.wlan.bjtu -42 -65 - -54
18 AP4 0a:69:6c:d6:91:27 eduroam -42 - -59 -51
19 AP1 0e:69:6c:d6:9c:bb web.wlan.bjtu -52 -60 - -56
19 AP2 16:69:6c:d6:9c:bb local.wlan.bjtu -53 -60 - -57
19 AP3 1a:69:6c:d6:9c:bb NULL -53 -60 - -57
19 AP4 12:69:6c:d6:9c:bb phone.wlan.bjtu -53 -60 - -57

7. Detailed design and implementation (详细设计与实现)

7.1 Subsystem design and implementation (子系统的设计与实现)

7.1.1 Class Diagram (类图)

This is all the activities(UIs), detailed information is in the UI part


This is all the classes:


AP & Point & Map & Positioning


Client, MyHandler, AcceptThread


Reader


FeedBack


MyListViewAdapter

7.1.2 User interface display (用户界面展示)

  • information query UI


  • Study button

-Office button

  • Other button

  • All button

7.2 Core algorithm (pseudo code) 核心算法(伪代码)

Client

  1. Connect with server, send and receive message
    private Client () {
        id = "";
        password = "";
        name = "";
        connect = false;
        quit = false;
    }

    public void connect() {
        try {
            client = new Socket("192.168.101.12", 2000);
            reader = new BufferedReader(new InputStreamReader(client.getInputStream()));
            writer = new PrintWriter(new OutputStreamWriter(client.getOutputStream()));
            connect = true;
        } catch (IOException e) {
            connect = false;
        }
    }

    public void disConnect() {
        try {
            reader.close();
            writer.close();
            client.close();
            connect = false;
            quit = true;
        } catch (IOException e) {
            System.exit(0);
        }
    }

    public void send(String message) {
        final String msg = message;
        new Thread(new Runnable() {
            @Override
            public void run() {
                writer.println(msg);
                writer.flush();
            }
        }).start();
    }

    public String receive() {
        String mes = "";
        try {
            mes = reader.readLine();
            return mes;
        } catch (IOException e) {
            return null;
        }
    }
  1. Message accept and distribute
        while (!c.isQuit()) {
            if (c.isConnect()) {
                String str = c.receive();
                if (str != null) {
                    String[] list = str.split("#");
                    int what = 0;
                    String msg = "";
                    switch(list[0]) {
                        case "YL":
                            c.setID(list[1]);
                            c.setPassword(list[2]);
                            c.setName(list[3]);
                            c.setNumber(list[4]);
                            c.setPersonality(list[5]);
                            what = 1;
                            msg += "Log in successfully!";
                            break;
                        case "NL":
                            what = 2;
                            msg += list[1] + "!";
                            break;
                        case "YR":
                            c.setID(list[1]);
                            what = 3;
                            msg += "Register successfully, your id is " + list[1] + "!";
                            break;
                        case "NR":
                            what = 4;
                            msg += list[1] + "!";
                            break;
                        case "YM1":
                            c.setPassword(list[1]);
                            what = 5;
                            msg += "Modify successfully!";
                            break;
                        case "NM1":
                            what = 6;
                            msg += list[1] + "!";
                            break;
                        case "YM2":
                            c.setName(list[1]);
                            c.setNumber(list[2]);
                            c.setPersonality(list[3]);
                            what = 7;
                            msg += "Modify successfully!";
                            break;
                        case "NM2":
                            what = 8;
                            msg += list[1] + "!";
                            break;
                        case "YQ":
                            if(list[1].equals("No feedbacks")) {
                                what = 10;
                                msg = list[1] + "!";
                            } else {
                                what = 9;
                                msg = str.substring(3, str.length() - 1);
                            }
                            break;
                        case "NQ":
                            what = 11;
                            msg = list[1] + "!";
                            break;
                        case "YF":
                            what = 12;
                            msg = "comment successfully!";
                            break;
                        case "NF":
                            what = 13;
                            msg = list[1] + "!";
                            break;
                    }
                    mh.sendMessage(mh.obtainMessage(what, msg));
                }
            } else {
                c.connect();
            }
        }
  1. Handler message and update UI
    @Override
    public void handleMessage(Message msg) {
        switch (msg.what) {
            case 1:
                Log.d("-------------------------", "Can");
                Toast.makeText(act.getApplicationContext(), msg.obj.toString(), Toast.LENGTH_SHORT).show();
                intent = new Intent(act, MenuActivity.class);
                act.startActivity(intent);
                break;
            case 3:
                Toast.makeText(act.getApplicationContext(), msg.obj.toString(), Toast.LENGTH_SHORT).show();
                intent = new Intent(act, LoginActivity.class);
                act.startActivity(intent);
                break;
            case 5:
                Toast.makeText(act.getApplicationContext(), msg.obj.toString(), Toast.LENGTH_SHORT).show();
                intent = new Intent(act, MyInfoActivity.class);
                act.startActivity(intent);
                break;
            case 9:
                RoomInfoActivity item = (RoomInfoActivity)act;
                String[] list = msg.obj.toString().split("#");
                int length = list.length;
                for (int i = 0; i < length; i += 2) {
                    item.addComment(list[i], list[i + 1]);
                }
                break;
            case 2:
            case 4:
            case 6:
            case 7:
            case 8:
            case 10:
            case 11:
            case 12:
            case 13:
                Toast.makeText(act.getApplicationContext(), msg.obj.toString(), Toast.LENGTH_SHORT).show();
                break;
        }

Server

  1. Connect with database, query and update content
        private Server() {
		try {
			Class.forName("org.sqlite.JDBC");
			System.out.println("Register driver!");
			String url = "jdbc:sqlite:data/InfoDB.db";
			c = DriverManager.getConnection(url);
			System.out.println("Establish connection!");
			stmt = c.createStatement();
		} catch (ClassNotFoundException e) {
			System.out.println("Driver registration failed!!");
			e.printStackTrace();
			return;
		} catch (SQLException e) {
			System.out.println("SQL Error!!");
			e.printStackTrace();
		}
	}
	
	public void closeDataBase() {
		try {
			stmt.close();
			c.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		
	}
	
	public String searchCustomer(int id, String password) {
		try {
			String sql = "select * from UserInfo;";
			ResultSet rs = stmt.executeQuery(sql);
			int i = 0;
			String p = "";
			while (rs.next()) {
				i = rs.getInt("id");
				p = rs.getString("password");
				if(id == i && password.equals(p)) {
					String name = rs.getString("name");
					String personality = rs.getString("personality");
					String number = rs.getString("number");
					String info = i + "#" + p + "#" + name + "#" + number + "#" + personality;
					rs.close();
					return info;
				} else if (id == i && !password.equals(p)) {
					rs.close();
					return "password is wrong";
				}
			}
			rs.close();
		} catch (SQLException e) {
			System.out.println("SQL Error!!");
		}
		return "user id doesn't exist";
	}
	
	public boolean modifyCustomer(int id, char type, String newOne) {
		if (!newOne.equals("#")) {
			String sql = null;
			if (type == 'P') {
				sql = "update UserInfo set password = '" + newOne + "' where id = " + id + ";";
			} else if (type == 'N') {
				sql = "update UserInfo set name = '" + newOne + "' where id = " + id + ";";
			} else if (type == 'Y') {
				sql = "update UserInfo set personality = '" + newOne + "' where id = " + id + ";";
			} else if (type == 'M') {
				sql = "update UserInfo set number = '" + newOne + "' where id = " + id + ";";
			}
			
			if(sql != null) {
				synchronized(obj) {
					try {
						stmt.executeUpdate(sql);
					} catch (SQLException e) {
						System.out.println("SQL Error!!");
						return false;
					}
				}
			}
		}
		return true;
	}
	
	public String insertCustomer(String name, String password) {
		try {
			String sql = "select * from UserInfo order by id desc limit 0,1";
			ResultSet rs = stmt.executeQuery(sql);
			int i = rs.getInt("id") + 1;
			rs.close();
			
			sql = "insert into UserInfo(id, password, name) values(" + i + ", '" + password + "', '" + name + "');";
			
			synchronized(obj) {
				stmt.executeUpdate(sql);
			}
			return i + "#" + password;
		} catch (SQLException e) {
			System.out.println("SQL Error!!");
		}
		return null;
	}
	
	public String getFeedback(String id) {
		String result = "";
		try {
			String sql = "select * from " + id + ";";
			ResultSet rs = stmt.executeQuery(sql);
			while (rs.next()) {
				result += "#" + rs.getString("name");
				result += "#" + rs.getString("feedback");
			}
			rs.close();
		} catch (SQLException e) {
			System.out.println("SQL Error!!");
			return "ID not found";
		}
		return result;
	}
	
	public boolean addFeedback(String id, String name, String feedback) {
		try {
			String sql = "insert into " + id + " values('" + feedback + "', '" + name + "');";
			synchronized(obj) {
				stmt.executeUpdate(sql);
			}
		} catch (SQLException e) {
			e.printStackTrace();
			System.out.println("SQL Error!!");
			return false;
		}
		return true;
	}
  1. Deal with message sent by client
    @Override
    public void run() {
        while (true) {
		    String x = accept();
		    if(x == null) {
		    	break;
		    }
		    String[] define = x.split("#");
		    String message = "";
			switch (define[0]) {
			case "L":
				info = ps.searchCustomer(Integer.parseInt(define[1]),define[2]);
		        if(info.equals("user id doesn't exist") || info.equals("password is wrong")) {
		            message="NL#" + info;
		            send(message);
		        } else {
		            isLogin = true;
		            String[] information = info.split("#");
		            id = Integer.parseInt(information[0]);
		            name = information[2];
		            message = "YL#" + info;
		            send(message);
		        }
				break;
			case "R":
				info = ps.insertCustomer(define[1], define[2]);
				if (info != null) {
					message = "YR" + "#" + info;
				} else {
					message = "NR" + "#" + "Name already exists";
				}
				send(message);
				break;
			case "M1":
				if(isLogin) {
					boolean s = ps.modifyCustomer(id, 'P', define[1]);
					message = s ? "Y" + x : "NM1#Something error";
					send(message);
				}
				break;
			case "M2":
				if(isLogin) {
					boolean s = ps.modifyCustomer(id, 'N', define[1]);
					boolean c = ps.modifyCustomer(id, 'M', define[2]);
					boolean u = ps.modifyCustomer(id, 'Y', define[3]);
					message = (s && u) && c ? "Y" + x : "NM2#Something error";
					send(message);
				}
				break;
			case "Q":
				if(isLogin) {
					String r = ps.getFeedback("F" + define[1]);
					if(r.equals("ID not found")) {
						message = "NQ#Query failed";
						send(message);
					} else {
						if(r.equals("")) {
							message = "YQ#No feedbacks";
						} else {
							message = "YQ" + r;
						}
						send(message);
					}
				}
				break;
			case "F":
				if(isLogin) {
					boolean s = ps.addFeedback("F" + define[1], define[2], define[3]);
					message = s ? "YF" : "NF#Something error";
					send(message);
				}
				break;
			case "E":
				if(isLogin) {
					System.out.println("Malfunction:");
					System.out.println("Room id: " + define[1]);
					System.out.println("Detail: " + define[2]);
				}
				break;
			}
		}
        System.out.println(client.getRemoteSocketAddress() + " disconnect");
    }

Positioning

For starters, I should tell you three maps which has different dimension.
First map is the 2-d map, that is the map which is going to display.

Second map is the 1-d map, that is the map which shows the correspondence between real room and roomID

switch(roomId) {
            case 1:
                roomName = "YF301";
                setTag(7);
                break;
            case 2:
                roomName = "YF302";
                setTag(1);
                break;
            case 3:
                roomName = "YF303";
                setTag(7);
                break;
            case 4:
                roomName = "YF304";
                setTag(1);
                break;
            case 5:
                roomName = "YF305";
                setTag(6);
                break;
            case 6:
                roomName = "EAST WC";
                setTag(2);
                break;
            case 7:
                roomName = "YF307";
                setTag(1);
                break;
            case 8:
                roomName = "YF308";
                setTag(1);
                break;
            case 9:
                roomName = "YF309";
                setTag(1);
                break;
            case 10:
                roomName = "YF310";
                setTag(1);
                break;
            case 12:
                roomName = "YF312";
                setTag(1);
                break;
            case 13:
                roomName = "YF313";
                setTag(7);
                break;
            case 14:
                roomName = "TEAHCER'S ROOM";
                setTag(3);
                break;
            case 15:
                roomName = "TOILET";
                setTag(2);
                break;
            case 16:
                roomName = "CAFE";
                setTag(4);
                break;
            case 17:
                roomName = "EAST STAIR";
                setTag(5);
                break;
            case 18:
                roomName = "WEST STAIR";
                setTag(5);
                break;
            case 19:
                roomName = "MIDDLE STAIR";
                setTag(5);
                break;
            default: break;
        }

Third map is the 4-d map, which record the strongest 4 AP information of each room.

Secondly, I am going to introduce 4 classes

  1. AP class
    This class represent the Access Points, it is our core value of positioning.
  2. Point class
    This class represent the Position Point, it has the coordinate value of every map(4-d map, 1-d map, 2-d map)
  3. Map class
    This is our 4-d map
  4. Positioning class
    This class include the major positioning algorithm

You can get your position by two calculate methods, by DIS or by COS. But the basic algorithm is similar.

You are going to use the function:

//major positioning code
    public int getMyPositionByDis(Point cPosition, Context context)
    {
        Reader r = new Reader(context);
        currentMap = r.creat_map(context);
        return findTheNearestPointByDis(cPosition, context).getId();
    }

    public int getMyPositionByCos(Point cPosition, Context context)
    {
        Reader r = new Reader(context);
        currentMap = r.creat_map(context);
        return findTheNearestPointByCos(cPosition, context).getId();
    }

And it will call this function to find the nearest point in map

private Point findTheNearestPointByDis(Point currentPositionPoint, final Context context)
    {
        Point nearestPoint = new Point();
        double minDis = MAX_DISTANCE;

        for (int i=1;i<currentMap.getPointList().size();i++)
        {
            Point cP = currentMap.getPoint(i, context);
            Log.d("PList:",cP.getAp1().getBSSID());
            double dis = calculateDis(cP, correctCoordinate(cP,currentPositionPoint));
            if (dis <= minDis)
            {
                minDis = dis;
                nearestPoint = cP;
            }
        }
        return nearestPoint;
    }

And this is the calculate function:

// calculate the Euclidean Distance
    private double calculateDis(Point p1, Point p2)
    {
        double distance = -1;


        distance = Math.sqrt((p1.getAp1().getLevel()-p2.getAp1().getLevel())*(p1.getAp1().getLevel()-p2.getAp1().getLevel())
                            +(p1.getAp2().getLevel()-p2.getAp2().getLevel())*(p1.getAp2().getLevel()-p2.getAp2().getLevel())
                            +(p1.getAp3().getLevel()-p2.getAp3().getLevel())*(p1.getAp3().getLevel()-p2.getAp3().getLevel())
                            +(p1.getAp4().getLevel()-p2.getAp4().getLevel())*(p1.getAp4().getLevel()-p2.getAp4().getLevel()));

        return distance;
    }
// calculate the cosine in 4-dimensional map
    private double calculateCos(Point p1, Point p2)
    {
        double cosine = -1; // 180° is impossible

        Point Opoint = new Point();
        cosine = calculateInnerProduct(p1,p2) / (calculateDis(p1,Opoint)*calculateDis(p2,Opoint));

        return cosine;
    }

    // calculate the inner product
    private double calculateInnerProduct(Point p1, Point p2) {
        double InnerProduct = -2;

        InnerProduct = (p1.getAp1().getLevel()*p2.getAp1().getLevel()
                        +p1.getAp2().getLevel()*p2.getAp2().getLevel()
                        +p1.getAp3().getLevel()*p2.getAp3().getLevel()
                        +p1.getAp4().getLevel()*p2.getAp4().getLevel());

        return InnerProduct;
    }

And if you read the code carefully, or think about the algorithm carefully, you will find a function called coordinate correction. This is necessary before we calculate the distance in 4-d map for the reason that there are too many APs in the map, so two point which is goint to calculate must be in the same coordinate. If it cannot find the corresponding AP, that means the current point is too far from the point in Map, so we assign a null AP as the AP in the new coordinate corrected point.

public Point correctCoordinate(Point pInMap, Point currentPosition)
    {
        Point newVirtualPoint = new Point();
        String BSSID1 = pInMap.getAp1().getBSSID();
        String BSSID2 = pInMap.getAp2().getBSSID();
        String BSSID3 = pInMap.getAp3().getBSSID();
        String BSSID4 = pInMap.getAp4().getBSSID();

        Iterator <AP> itr = currentPosition.getAPList().iterator();
       


        int exist[]={0,0,0,0};

        while(itr.hasNext())
        {

            AP ap = itr.next();

            if (ap.getBSSID().equals(BSSID1))
            {
                newVirtualPoint.setAp1(ap);
                exist[0]=1;
            }
            if (ap.getBSSID().equals(BSSID2))
            {
                newVirtualPoint.setAp2(ap);
                exist[1]=1;
            }
            if (ap.getBSSID().equals(BSSID3))
            {
                newVirtualPoint.setAp3(ap);
                exist[2]=1;
            }
            if (ap.getBSSID().equals(BSSID4))
            {
                newVirtualPoint.setAp4(ap);
                exist[3]=1;
            }
        }

        for(int i=0;i<4;i++){
            AP null_ap=new AP("00:00:00:00:00:00","",-200);
            if(exist[i]==0){
                switch (i){
                    case 1:
                        newVirtualPoint.setAp1(null_ap);
                        break;
                    case 2:
                        newVirtualPoint.setAp2(null_ap);
                        break;
                    case 3:
                        newVirtualPoint.setAp3(null_ap);
                        break;
                    case 4:
                        newVirtualPoint.setAp4(null_ap);
                        break;
                }
            }
        }
        return newVirtualPoint;
    }

ListviewAdapter

the user-defined adapter of the listview

public class MyListViewAdapter extends ArrayAdapter {
    private int resourceID;
    public MyListViewAdapter(Context context, int textViewResourceId, List<MyListView> objects) {
        super(context, textViewResourceId, objects);
        resourceID = textViewResourceId;
    }

    public View getView(int p, View convertView, ViewGroup parent) {
        MyListView listView = (MyListView) getItem(p);

        View view = LayoutInflater.from(getContext()).inflate(resourceID, null);
        ImageView listImage = (ImageView) view.findViewById(R.id.pImage);
        TextView listName = (TextView) view.findViewById(R.id.pMessage);

        listImage.setImageResource(listView.getImageID());
        listName.setText(listView.getPosition());

        return view;
    }
}

Information query:

After you press the search button, the num of the searchText will be sended to this Class. This class will choose the room whose roomID contains the key num and display them on the listview. This class also contails the response function of the item and send roomID to the next activity.

public class SearchActivity extends AppCompatActivity {
    private List<MyListView> lv = new ArrayList<MyListView>();
    private String num;
    String[] idList = {"1","2","3","4","5","6","7","8","9","10","12","13","14","15","16","17","18","19"};
    String[] nameList = {"YF301","YF302","YF303","YF304","YF305","EAST WC","YF307","YF308","YF309","YF310","YF312",
            "YF313","TEAHCER'S ROOM","TOILET","CAFE","EAST STAIR","WEST STAIR","MIDDLE STAIR"};
    int[] image1 = {R.drawable.orange, R.drawable.yintao, R.drawable.apple, R.drawable.apple, R.drawable.orange,
            R.drawable.yintao, R.drawable.apple, R.drawable.apple,
            R.drawable.orange, R.drawable.yintao, R.drawable.apple,
            R.drawable.apple, R.drawable.orange, R.drawable.yintao, R.drawable.apple, R.drawable.apple,
            R.drawable.orange, R.drawable.yintao, R.drawable.apple, R.drawable.apple};
    Point point = new Point();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.commonlist_layout);
        num = getIntent().getStringExtra("num");
        initListView();
        MyListViewAdapter myListViewAdapter = new MyListViewAdapter(SearchActivity.this, R.layout.listview_item,lv);
        ListView listView1 = (ListView)findViewById(R.id.list_view);
        listView1.setAdapter(myListViewAdapter);
        listView1.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            public void onItemClick(AdapterView<?> parent, View view, int index, long id) {
                String send = (lv.get(index).getRoomID());

                Intent intent = new Intent(SearchActivity.this, RoomInfoActivity.class);
                intent.putExtra("Point", send);
                startActivity(intent);
            }
        });
    }

    private void initListView() {
        for(int i = 0; i < nameList.length; i++) {
            if(nameList[i].contains(num) || idList[i].contains(num)) {
                point.setAllVars(Integer.parseInt(idList[i]));
                MyListView li = new MyListView(idList[i], nameList[i], image1[i]);
                lv.add(li);
            }
        }
    }
}

This class will get the detailed information of the room by the roomID and display them on the detailed interfce. The comment button and the remind button clicked function is writed in the class.

public class RoomInfoActivity extends AppCompatActivity {
    EditText editComment;
    TextView feedback;
    TextView idName;
    ImageView photo;
    Button comment;
    Button remind;
    int roomID;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.roominfo_layout);

        String receive = getIntent().getStringExtra("Point");
        roomID = Integer.valueOf(receive);
        Point p = new Point(roomID);
        p.setAllVars(roomID);

        MyHandler.getMyHandler().setActivity(RoomInfoActivity.this);
        //Client.getClient().send("Q#" + roomID);

        idName = (TextView) findViewById(R.id.idname);
        editComment = (EditText) findViewById(R.id.editComment);
        feedback = (TextView) findViewById(R.id.tFeedback);
        photo = (ImageView) findViewById(R.id.picture);

        String message1 = p.getRoomName();
        String tagName = p.getTagName();
        idName.setText(message1 + " : " + tagName);

        comment = (Button) findViewById(R.id.commentbtn);
        comment.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                String com = editComment.getText().toString();
                if(com != null && !com.equals("")) {
                    //Client.getClient().send("F#" + roomID + "#" + Client.getClient().getName() + "#" + com);
                    editComment.setText((""));
                } else {
                    Toast.makeText(getApplicationContext(), "Comment text is empty!", Toast.LENGTH_SHORT).show();
                }
            }
        });

        remind = (Button) findViewById(R.id.remindbtn);
        remind.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(RoomInfoActivity.this,RemindActivity.class);
                intent.putExtra("ID", roomID + "");
                startActivity(intent);
            }
        });
    }

    public void addComment(String name, String f) {
        feedback.append("@" + name + ": " + f + "\n");
    }
}

Study、Office、Other、All button:

these buttons are similar, so I only display a example to show the progress
The roomID and tagName of the related button are stored in the class, the class will display these information on the listview and send the roomID to the RoomInfoActivity.

public class OthersActivity extends AppCompatActivity {
    private List<MyListView> lv = new ArrayList<MyListView>();
    String[] idList = {"15","16","17","18","19"};
    String[] nameList = {"TOILET","CAFE","EAST STAIR","WEST STAIR","MIDDLE STAIR"};
    int[] image = {R.drawable.orange, R.drawable.yintao, R.drawable.apple,
            R.drawable.apple, R.drawable.orange};

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.commonlist_layout);

        initListView();

        MyListViewAdapter myListViewAdapter = new MyListViewAdapter(OthersActivity.this,R.layout.listview_item,lv);
        ListView listView1 = (ListView)findViewById(R.id.list_view);
        listView1.setAdapter(myListViewAdapter);
        listView1.setOnItemClickListener(new AdapterView.OnItemClickListener(){
            public void onItemClick(AdapterView<?> parent,View view,int index,long id){
                String send = (lv.get(index).getRoomID());

                Intent intent = new Intent(OthersActivity.this, RoomInfoActivity.class);
                intent.putExtra("Point", send);
                startActivity(intent);
            }
        });
    }

    private void initListView() {
        for(int i = 0; i < 5; i++) {
            MyListView yt = new MyListView(idList[i], nameList[i], image[i]);
            lv.add(yt);
        }
    }
}


This class will get the detailed information of the room by the roomID and display them on the detailed interfce. The comment button and the remind button clicked function is writed in the class.

public class RoomInfoActivity extends AppCompatActivity {
    EditText editComment;
    TextView feedback;
    TextView idName;
    ImageView photo;
    Button comment;
    Button remind;
    int roomID;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.roominfo_layout);

        String receive = getIntent().getStringExtra("Point");
        roomID = Integer.valueOf(receive);
        Point p = new Point(roomID);
        p.setAllVars(roomID);

        MyHandler.getMyHandler().setActivity(RoomInfoActivity.this);
        //Client.getClient().send("Q#" + roomID);

        idName = (TextView) findViewById(R.id.idname);
        editComment = (EditText) findViewById(R.id.editComment);
        feedback = (TextView) findViewById(R.id.tFeedback);
        photo = (ImageView) findViewById(R.id.picture);

        String message1 = p.getRoomName();
        String tagName = p.getTagName();
        idName.setText(message1 + " : " + tagName);

        comment = (Button) findViewById(R.id.commentbtn);
        comment.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                String com = editComment.getText().toString();
                if(com != null && !com.equals("")) {
                    //Client.getClient().send("F#" + roomID + "#" + Client.getClient().getName() + "#" + com);
                    editComment.setText((""));
                } else {
                    Toast.makeText(getApplicationContext(), "Comment text is empty!", Toast.LENGTH_SHORT).show();
                }
            }
        });

        remind = (Button) findViewById(R.id.remindbtn);
        remind.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(RoomInfoActivity.this,RemindActivity.class);
                intent.putExtra("ID", roomID + "");
                startActivity(intent);
            }
        });
    }

    public void addComment(String name, String f) {
        feedback.append("@" + name + ": " + f + "\n");
    }
}

7.3 Interface design (接口设计)

Server

CLASS NAME FUNCTION INPUT OUTPUT
Server class searchCustomer id, password search_result
Server class modifyCustomer id, type, newOne modify_result
Server class insertCustomer name, password insert_result
Server class getFeedback room_id feedbacks
Server class addFeedback room_id, user_name, feedback result

Client

CLASS NAME FUNCTION INPUT OUTPUT
Client class connect null null
Client class send message_send null
Client class receive null message_received
MyHandler setActivity app_activity null
MyHandler setActivity app_activity null

Positioning

This is a singleTon, so you can call all the public functions by using:

Positioning.positioningTool.//Here is the function calling
CLASS NAME FUNCTION INPUT OUTPUT
Positioning getMyPositionByDIS currentPoint roomID
Positioning getMyPositionByCOS currentPoint roomID

Mission record (任务记录)

DAY1(2020-06-29)

名字 完成任务 占比(总和100%) 备注
钟沁堃 配置环境,制定项目大纲 大纲包括基础功能、扩展功能包含哪些,以及何时完成何任务,分配任务,绘制甘特图,建立github目录,编写并细化项目需求
刘嘉许 配置环境
何兰兰 配置环境
何毛鑫 配置环境
章富 配置环境
黄 林 配置环境

DAY2(2020-06-30)

名字 完成任务 占比(总和100%) 备注
钟沁堃 学习并制定核心定位流程 包括学习应该先做什么(WIFISCAN)后做什么(定位算法)
何毛鑫 熟悉GitHub以及项目需求
何兰兰 学习安卓开发知识
章富 熟悉github以及项目需求,确定服务器与客户端TCP协议
黄林 熟悉github以及项目需求,学习安卓开发相关知识
刘嘉许 熟悉github以及项目需求,学习安卓开发,学习modao的使用

DAY3(2020-07-01)

名字 完成任务 占比(总和100%) 备注
钟沁堃 B-F-Positioning Wifi Scanning program (not finished)
何毛鑫 编写客户端代码
章富 完成搭建初始服务器,服务器链接好数据库
黄林 修改客户端代码
何兰兰 修改客户端代码
刘嘉许 编写项目需求文档,开始设计UI模型

DAY4(2020-07-02)

Finished ppt, requirements analysis document, coding of UI connections, and learning KNN algorithm.

名字 完成任务 占比(总和100%) 备注
钟沁堃 B-F-Positioning Wifi Scanning program (finished),Combined with UI
何毛鑫 编写服务器代码
章富 整合客户端代码,测试初始服务器和初始客户端的连接
黄林 撰写需求文档,准备第一次答辩ppt
何兰兰 撰写需求文档
刘嘉许 完成并完善modao上的设计UI原型

This is the tabel shows that every pages corresponding relation

This is the UI that has finished

DAY5(2020-07-03)

application combining and learning KNN.

名字 完成任务 占比(总和100%) 备注
钟沁堃 B-F-Positioning Combie the wifiscan with our app
何毛鑫 修改,完善服务器代码
章富 将java客户端整合入安卓APP内
刘嘉许 在Androidstudio上实现所有界面及其代码,整理项目对照表
黄林 学习指纹定位算法,绘制用例图
何兰兰 学习安卓知识,熟悉项目

DAY6(2020-07-04)

Continue to Finish the network part.
We have finished the WIFISCAN part, and we are recording the position point information.
We began to code the positioning part.

名字 完成任务 占比(总和100%) 备注
钟沁堃 B-F-Positioning Finished the WIFISCAN part & record the point information
何毛鑫 熟悉KNN算法
章富 解决安卓网络连接的问题,采用Thread和Handler模型
刘嘉许 实现所有界面间联通跳转和按键响应
黄林 记录四维地图信息
何兰兰 学习listview写法

DAY7(2020-07-05)

Today’s tasks:

  • Finish the map display on the phone
  • Finish writing the 4-d map in the dataBase
  • Finish get data from the dataBase
名字 完成任务 占比(总和100%) 备注
钟沁堃 B-F-Positioning Finished positioning algorithm
何毛鑫 基本掌握KNN算法,并录入wifi信号强度数据
章富 成功解决网络连接问题,实现登陆注册以及相关容错
黄林 学习处理数据方法
何兰兰 设计并实现listview界面
刘嘉许 学习KNN算法,协助数据录入

DAY8(2020-07-06)

名字 完成任务 占比(总和100%) 备注
钟沁堃 B-F-Positioning 优化定位算法,提高精度,容错率
何毛鑫 编写代码将wifi信号强度数据导入数据库,并编写获取相应信息的工具类
章富 整理美化界面UI
黄林 辅助在数据库中绘制四维map
何兰兰 实现listview的子item的响应
刘嘉许 学习listview使用,完成平台规则界面

DAY9(2020-07-07)

名字 完成任务 占比(总和100%) 备注
钟沁堃 B-F-Positioning 优化定位算法,提高精度,容错率
何毛鑫 绘制数据库ER图,并修改部分定位算法
章富 用户信息词条增加,修改相应的TCP协议,将新的信息收发写入客户端和服务器
黄林 学习android开发及附加功能需用到的知识
何兰兰 将写好的listview整合到主界面的周边推荐按钮
刘嘉许 实现地图map界面的显示

DAY10(2020-07-08)

完成基础功能部分,开始扩展功能

名字 完成任务 占比(总和100%) 备注
钟沁堃 B-F-Positioning 优化定位算法,提高精度,容错率,演示小组app,制作演示视频
何毛鑫 绘制UML类图,修改定位算法
章富 绘制数据库ER图,协助解决客户端数据库问题
黄林 制作第二次评审ppt
何兰兰 实现拓展功能的information query部分
刘嘉许 完成地图和按键的显示

DAY11(2020-07-09)

开始扩展功能部分

名字 完成任务 占比(总和100%) 备注
钟沁堃 E-P 明确并分配扩展部分任务,开始制作课堂签到功能
何毛鑫 解决安卓中的文件读取问题,完善代码
章富 附加功能信息录入数据库,添加对应的TCP协议
黄林 设计listview的子item,学写故障报修
何兰兰 完善information query部分
刘嘉许 设计评论功能,学习listview,协助查找bug

DAY12(2020-07-10)

名字 完成任务 占比(总和100%) 备注
钟沁堃 E-P 决定删去签到功能,制作元素推荐功能
何毛鑫 辅助修改定位算法
章富 完成附加功能,将Thread和Handler实现成单例,汇总网络信息传输以及控制UI界面更新
黄林 完成故障报修附加功能
刘嘉许 图片素材收集和制作,设计最终UI,帮助实现评论功能
何兰兰 帮助实现拓展部分的故障报修功能

DAY13(2020-07-11)

名字 完成任务 占比(总和100%) 备注
钟沁堃 E-P 完成制作元素推荐功能,开始代码整合
何毛鑫 绘制整个项目的UML类图
章富 整合所有附加功能,修复Bug
刘嘉许 完成最终的UI的布局和美化
黄林 编写项目文档
何兰兰 实现主界面的自习室、办公室、其他、全部按钮

DAY14(2020-07-12)

代码整合,最后的debug,预演示,定位精度,软件功耗测评

名字 完成任务 占比(总和100%) 备注
钟沁堃 ENDING 代码最后整合,全部bug all clear,软件测评,完成测评文档、软件设计说明书
章富 编写相关项目文档
黄林 制作答辩ppt part(1-3,6)
刘嘉许 编写相关项目文档
何兰兰 撰写答辩文档
何毛鑫 编写相关项目文档

猜你喜欢

转载自blog.csdn.net/RaynorFTD/article/details/109293533