├── .gitignore ├── LICENSE.txt ├── Node ├── package-lock.json ├── package.json └── phonepi.js ├── Python ├── Flask │ ├── PhonePi.py │ └── requirements.txt └── WebSocket │ ├── PhonePi.py │ └── requirements.txt └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Priyankar Kumar 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Node/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "phonepi_node", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "ip": { 8 | "version": "1.1.5", 9 | "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", 10 | "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=" 11 | }, 12 | "ws": { 13 | "version": "7.4.6", 14 | "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz", 15 | "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==" 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Node/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "phonepi_node", 3 | "version": "1.0.0", 4 | "description": "This is a companion server to the PhonePi Sensor Streamer app", 5 | "main": "phonePi.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "start": "node phonepi" 9 | }, 10 | "keywords": [ 11 | "phonepi" 12 | ], 13 | "author": "Priyankar Kumar", 14 | "license": "MIT", 15 | "dependencies": { 16 | "ip": "^1.1.5", 17 | "ws": "^7.4.6" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Node/phonepi.js: -------------------------------------------------------------------------------- 1 | const ip = require("ip"); 2 | const ws = require("ws"); 3 | const WebSocket = require("ws"); 4 | const http = require("http"); 5 | const fs = require("fs"); 6 | const url = require("url"); 7 | 8 | console.dir(`Please enter ${ip.address()}:5000 in the app [PhonePi] or just ${ip.address()} [PhonePi+]`); 9 | 10 | var httpServer = http.createServer(); 11 | 12 | const accelerometerWSS = new WebSocket.Server({ 13 | noServer: true 14 | }); 15 | 16 | const gyroscopeWSS = new WebSocket.Server({ 17 | noServer: true 18 | }); 19 | 20 | const magnetometerWSS = new WebSocket.Server({ 21 | noServer: true 22 | }); 23 | 24 | const orientationWSS = new WebSocket.Server({ 25 | noServer: true 26 | }); 27 | 28 | const stepCounterWSS = new WebSocket.Server({ 29 | noServer: true 30 | }); 31 | 32 | const thermometerWSS = new WebSocket.Server({ 33 | noServer: true 34 | }); 35 | 36 | const lightSensorWSS = new WebSocket.Server({ 37 | noServer: true 38 | }); 39 | 40 | const proximityWSS = new WebSocket.Server({ 41 | noServer: true 42 | }); 43 | 44 | const geolocationWSS = new WebSocket.Server({ 45 | noServer: true 46 | }); 47 | 48 | accelerometerWSS.on("connection", ws => { 49 | const writeStream = fs.createWriteStream("accelerometer.txt", { flags: "a" }); 50 | ws.on("message", message => { 51 | console.log(`Received message => ${message}`); 52 | writeStream.write(message + "\n"); 53 | }); 54 | }); 55 | 56 | gyroscopeWSS.on("connection", ws => { 57 | const writeStream = fs.createWriteStream("gyroscope.txt", { flags: "a" }); 58 | ws.on("message", message => { 59 | console.log(`Received message => ${message}`); 60 | writeStream.write(message + "\n"); 61 | }); 62 | }); 63 | 64 | magnetometerWSS.on("connection", ws => { 65 | const writeStream = fs.createWriteStream("magnetometer.txt", { flags: "a" }); 66 | ws.on("message", message => { 67 | console.log(`Received message => ${message}`); 68 | writeStream.write(message + "\n"); 69 | }); 70 | }); 71 | 72 | orientationWSS.on("connection", ws => { 73 | const writeStream = fs.createWriteStream("orientation.txt", { flags: "a" }); 74 | ws.on("message", message => { 75 | console.log(`Received message => ${message}`); 76 | writeStream.write(message + "\n"); 77 | }); 78 | }); 79 | 80 | stepCounterWSS.on("connection", ws => { 81 | const writeStream = fs.createWriteStream("stepcounter.txt", { flags: "a" }); 82 | ws.on("message", message => { 83 | console.log(`Received message => ${message}`); 84 | writeStream.write(message + "\n"); 85 | }); 86 | }); 87 | 88 | thermometerWSS.on("connection", ws => { 89 | const writeStream = fs.createWriteStream("thermometer.txt", { flags: "a" }); 90 | ws.on("message", message => { 91 | console.log(`Received message => ${message}`); 92 | writeStream.write(message + "\n"); 93 | }); 94 | }); 95 | 96 | lightSensorWSS.on("connection", ws => { 97 | const writeStream = fs.createWriteStream("lightsensor.txt", { flags: "a" }); 98 | ws.on("message", message => { 99 | console.log(`Received message => ${message}`); 100 | writeStream.write(message + "\n"); 101 | }); 102 | }); 103 | 104 | proximityWSS.on("connection", ws => { 105 | const writeStream = fs.createWriteStream("proximity.txt", { flags: "a" }); 106 | ws.on("message", message => { 107 | console.log(`Received message => ${message}`); 108 | writeStream.write(message + "\n"); 109 | }); 110 | }); 111 | 112 | geolocationWSS.on("connection", ws => { 113 | const writeStream = fs.createWriteStream("geolocation.txt", { flags: "a" }); 114 | ws.on("message", message => { 115 | console.log(`Received message => ${message}`); 116 | writeStream.write(message + "\n"); 117 | }); 118 | }); 119 | 120 | httpServer.on("upgrade", function upgrade(request, socket, head) { 121 | const pathname = url.parse(request.url).pathname; 122 | 123 | if (pathname === "//accelerometer") { 124 | accelerometerWSS.handleUpgrade(request, socket, head, function done(ws) { 125 | accelerometerWSS.emit("connection", ws, request); 126 | }); 127 | } else if (pathname === "//gyroscope") { 128 | gyroscopeWSS.handleUpgrade(request, socket, head, function done(ws) { 129 | gyroscopeWSS.emit("connection", ws, request); 130 | }); 131 | } else if (pathname === "//magnetometer") { 132 | magnetometerWSS.handleUpgrade(request, socket, head, function done(ws) { 133 | magnetometerWSS.emit("connection", ws, request); 134 | }); 135 | } else if (pathname === "//orientation") { 136 | orientationWSS.handleUpgrade(request, socket, head, function done(ws) { 137 | orientationWSS.emit("connection", ws, request); 138 | }); 139 | } else if (pathname === "//stepcounter") { 140 | stepCounterWSS.handleUpgrade(request, socket, head, function done(ws) { 141 | stepCounterWSS.emit("connection", ws, request); 142 | }); 143 | } else if (pathname === "//thermometer") { 144 | thermometerWSS.handleUpgrade(request, socket, head, function done(ws) { 145 | thermometerWSS.emit("connection", ws, request); 146 | }); 147 | } else if (pathname === "//lightsensor") { 148 | lightSensorWSS.handleUpgrade(request, socket, head, function done(ws) { 149 | lightSensorWSS.emit("connection", ws, request); 150 | }); 151 | } else if (pathname === "//proximity") { 152 | proximityWSS.handleUpgrade(request, socket, head, function done(ws) { 153 | proximityWSS.emit("connection", ws, request); 154 | }); 155 | } else if (pathname === "//geolocation") { 156 | geolocationWSS.handleUpgrade(request, socket, head, function done(ws) { 157 | geolocationWSS.emit("connection", ws, request); 158 | }); 159 | } else { 160 | socket.destroy(); 161 | } 162 | }); 163 | 164 | httpServer.listen(5000, "0.0.0.0"); 165 | -------------------------------------------------------------------------------- /Python/Flask/PhonePi.py: -------------------------------------------------------------------------------- 1 | from flask import Flask 2 | from flask_sockets import Sockets 3 | import socket 4 | 5 | def get_ip(): 6 | s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 7 | try: 8 | # doesn't even have to be reachable 9 | s.connect(('10.255.255.255', 1)) 10 | IP = s.getsockname()[0] 11 | except Exception: 12 | IP = '127.0.0.1' 13 | finally: 14 | s.close() 15 | return IP 16 | 17 | hostname = socket.gethostname() 18 | IPAddr = get_ip() 19 | print("Your Computer Name is: " + hostname) 20 | print("Your Computer IP Address is: " + IPAddr) 21 | print("Enter {0}:5000 in the app [PhonePi] and select the sensors to stream. For PhonePi+ just enter {0}, without the port".format(IPAddr)) 22 | 23 | app = Flask(__name__) 24 | sockets = Sockets(app) 25 | 26 | 27 | @sockets.route('/accelerometer') 28 | def echo_socket(ws): 29 | f = open("accelerometer.txt", "a") 30 | while True: 31 | message = ws.receive() 32 | print(message) 33 | ws.send(message) 34 | print(message, file=f) 35 | f.close() 36 | 37 | 38 | @sockets.route('/gyroscope') 39 | def echo_socket(ws): 40 | f = open("gyroscope.txt", "a") 41 | while True: 42 | message = ws.receive() 43 | print(message) 44 | ws.send(message) 45 | print(message, file=f) 46 | f.close() 47 | 48 | 49 | @sockets.route('/magnetometer') 50 | def echo_socket(ws): 51 | f = open("magnetometer.txt", "a") 52 | while True: 53 | message = ws.receive() 54 | print(message) 55 | ws.send(message) 56 | print(message, file=f) 57 | f.close() 58 | 59 | 60 | @sockets.route('/orientation') 61 | def echo_socket(ws): 62 | f = open("orientation.txt", "a") 63 | while True: 64 | message = ws.receive() 65 | print(message) 66 | ws.send(message) 67 | print(message, file=f) 68 | f.close() 69 | 70 | 71 | @sockets.route('/stepcounter') 72 | def echo_socket(ws): 73 | f = open("stepcounter.txt", "a") 74 | while True: 75 | message = ws.receive() 76 | print(message) 77 | ws.send(message) 78 | print(message, file=f) 79 | f.close() 80 | 81 | 82 | @sockets.route('/thermometer') 83 | def echo_socket(ws): 84 | f = open("thermometer.txt", "a") 85 | while True: 86 | message = ws.receive() 87 | print(message) 88 | ws.send(message) 89 | print(message, file=f) 90 | f.close() 91 | 92 | 93 | @sockets.route('/lightsensor') 94 | def echo_socket(ws): 95 | f = open("lightsensor.txt", "a") 96 | while True: 97 | message = ws.receive() 98 | print(message) 99 | ws.send(message) 100 | print(message, file=f) 101 | f.close() 102 | 103 | 104 | @sockets.route('/proximity') 105 | def echo_socket(ws): 106 | f = open("proximity.txt", "a") 107 | while True: 108 | message = ws.receive() 109 | print(message) 110 | ws.send(message) 111 | print(message, file=f) 112 | f.close() 113 | 114 | 115 | @sockets.route('/geolocation') 116 | def echo_socket(ws): 117 | f = open("geolocation.txt", "a") 118 | while True: 119 | message = ws.receive() 120 | print(message) 121 | ws.send(message) 122 | print(message, file=f) 123 | f.close() 124 | 125 | 126 | @app.route('/') 127 | def hello(): 128 | return 'Hello World!' 129 | 130 | 131 | if __name__ == "__main__": 132 | from gevent import pywsgi 133 | from geventwebsocket.handler import WebSocketHandler 134 | server = pywsgi.WSGIServer( 135 | ('0.0.0.0', 5000), app, handler_class=WebSocketHandler) 136 | server.serve_forever() 137 | -------------------------------------------------------------------------------- /Python/Flask/requirements.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/priyankark/PhonePi_SampleServer/b2fb37cba4f697ed1e58e1bf6d0fcd04f10cd24e/Python/Flask/requirements.txt -------------------------------------------------------------------------------- /Python/WebSocket/PhonePi.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import asyncio 4 | import websockets 5 | import socket 6 | 7 | 8 | def get_ip(): 9 | s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 10 | try: 11 | # doesn't even have to be reachable 12 | s.connect(('10.255.255.255', 1)) 13 | IP = s.getsockname()[0] 14 | except Exception: 15 | IP = '127.0.0.1' 16 | finally: 17 | s.close() 18 | return IP 19 | 20 | 21 | hostname = socket.gethostname() 22 | IPAddr = get_ip() 23 | print("Your Computer Name is: " + hostname) 24 | print("Your Computer IP Address is: " + IPAddr) 25 | print("Enter {0}:5000 in the app [PhonePi] and select the sensors to stream. For PhonePi+ just enter {0}, without the port".format(IPAddr)) 26 | 27 | 28 | async def echo(websocket, path): 29 | async for message in websocket: 30 | if path == '//accelerometer': 31 | data = await websocket.recv() 32 | print(data) 33 | f = open("accelerometer.txt", "a") 34 | f.write(data+"\n") 35 | 36 | if path == '//gyroscope': 37 | data = await websocket.recv() 38 | print(data) 39 | f = open("gyroscope.txt", "a") 40 | f.write(data+"\n") 41 | 42 | if path == '//magnetometer': 43 | data = await websocket.recv() 44 | print(data) 45 | f = open("magnetometer.txt", "a") 46 | f.write(data+"\n") 47 | 48 | if path == '//orientation': 49 | data = await websocket.recv() 50 | print(data) 51 | f = open("orientation.txt", "a") 52 | f.write(data+"\n") 53 | 54 | if path == '//stepcounter': 55 | data = await websocket.recv() 56 | print(data) 57 | f=open("stepcounter.txt", "a") 58 | f.write(data+"\n") 59 | 60 | if path == '//thermometer': 61 | data = await websocket.recv() 62 | print(data) 63 | f=open("thermometer.txt", "a") 64 | f.write(data+"\n") 65 | 66 | if path == '//lightsensor': 67 | data = await websocket.recv() 68 | print(data) 69 | f=open("lightsensor.txt", "a") 70 | f.write(data+"\n") 71 | 72 | if path == '//proximity': 73 | data = await websocket.recv() 74 | print(data) 75 | f=open("proximity.txt", "a") 76 | f.write(data+"\n") 77 | 78 | if path == '//geolocation': 79 | data = await websocket.recv() 80 | print(data) 81 | f=open("geolocation.txt", "a") 82 | f.write(data+"\n") 83 | 84 | asyncio.get_event_loop().run_until_complete( 85 | websockets.serve(echo, '0.0.0.0', 5000)) 86 | asyncio.get_event_loop().run_forever() 87 | -------------------------------------------------------------------------------- /Python/WebSocket/requirements.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/priyankark/PhonePi_SampleServer/b2fb37cba4f697ed1e58e1bf6d0fcd04f10cd24e/Python/WebSocket/requirements.txt -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # [DEPRECATED] 2 | 3 | # PhonePi_SampleServer 4 | These are simple servers with WebSocket support that accept the sensor data and write it to a text file. These are companion sample servers for the PhonePi Sensor Streamer app. 5 | 6 | # Migration Notice 7 | Due to changes in the Android ecosystem since the last time the app was updated, we have had to re-write PhonePi. Also we have few extra sensors like camera and mic available in the new version. All new users are requested to download the "Sensor Stream" app (https://play.google.com/store/apps/details?id=com.priykum.SensorStream) especially if you have an Android version >= X. All new updates will be made to this app. 8 | 9 | We will continue to support "PhonePi" and "PhonePi+" for as long as feasible and atleast until the new version achieves feature parity with PhonePi+. 10 | 11 | # Steps: 12 | * Clone the repository or download the zip file and unzip it to a directory of your choice. 13 | 14 | ## To Run the Python Server (version >= Python 3.0) 15 | 16 | * Make sure you have python (version >=3) installed and you can access both pip and python from the command line/ terminal 17 | * To check the same open command line/terminal and type `python --version` and `pip --version` 18 | * There are two servers available in Python, one uses Flask and Flask_Sockets and the other uses Websockets with async io. Both should work well. Choose as per your requirements. 19 | * cd to the directory where the folder was extracted in the command line 20 | * Optional Step: It's highly recommended, you create a virtual env before installing dependencies. Activate the virtual environment and proceed. OS specific steps are available in the docs [https://packaging.python.org/guides/installing-using-pip-and-virtual-environments/] 21 | 22 | **Brief Summary of steps to follow to create virtual env [Optional Step]** 23 | ``` 24 | cd Python 25 | cd Flask or cd WebSocket # Depending upon which server you want to use 26 | py -m venv env # Create virtual env 27 | source env/bin/activate (On Linux or Mac) or .\env\Scripts\activate (On Windows) 28 | ``` 29 | 30 | **Final Installation and run steps** 31 | ``` 32 | cd PhonePi_SampleServer-master/Python 33 | cd Flask or cd WebSocket # Depending upon which server you want to use 34 | pip install -r requirements.txt 35 | python3 PhonePi.py 36 | ``` 37 | ## To run the Node Server (latest version recommended) 38 | 39 | ``` 40 | cd Node 41 | npm install 42 | npm start 43 | ``` 44 | 45 | ## To use the app 46 | * Make sure both your phone and the laptop/raspi are on same network. 47 | * Find the internal ip address of the raspi/laptop 48 | * If you are using Phone Pi and not Phone Pi+, simply type the ip address:5000.Example: 192.168.1.24:5000 in the app's input bar. 49 | * You don't need the port number if you are using Phone Pi+. Just input the ip address. Example: 192.168.1.24 50 | * Switch on whatever sensor's data you want to stream. 51 | 52 | You can make any changes you want to to PhonePi.py or PhonePi.js 53 | 54 | ## Data Format Cheat sheet: 55 | * Accelerometer: x,y,z 56 | * Gyroscope: x,y,z 57 | * Magnetometer: x,y,z 58 | * Orientation: azimuth,pitch,roll 59 | * Step Counter: steps 60 | * Thermometer: temperature 61 | * Light Sensor: light 62 | * Proximity: isNear, value, maxRange 63 | * Link: https://github.com/kprimice/react-native-sensor-manager 64 | 65 | # Server details (Python) 66 | This makes use of flask_sockets. Note the use of namespaces which are in accordance with the sensor's name. Sample code: 67 | 68 | ```python 69 | @sockets.route('/accelerometer') 70 | def echo_socket(ws): 71 | f=open("accelerometer.txt","a") 72 | while True: 73 | message = ws.receive() 74 | print(message) 75 | ws.send(message) 76 | print>>f,message 77 | f.close() 78 | ``` 79 | The app would then establish a connection to ws://url//accelerometer 80 | where url is what the user enters (ip address:port) 81 | 82 | ## Contribution guidelines 83 | This repository is open to contributions. 84 | On the server side, we are looking to support sample servers in more languages and frameworks such as node.js, Go etc. 85 | Please feel free to raise PRs! 86 | 87 | ### For more support, please e-mail priyankar.kumar98@gmail.com 88 | --------------------------------------------------------------------------------