Compare commits
5 commits
Execute_Sc
...
main
Author | SHA1 | Date | |
---|---|---|---|
|
be55add3f3 | ||
|
f2ac8871e5 | ||
|
a8fbb578e8 | ||
|
e97c2815be | ||
|
ff5a2e51e9 |
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -2,3 +2,6 @@ src/**/__pycache__
|
||||||
src/venv
|
src/venv
|
||||||
src/modules/navigationd/*.png
|
src/modules/navigationd/*.png
|
||||||
src/modules/navigationd/cache
|
src/modules/navigationd/cache
|
||||||
|
src/logs
|
||||||
|
src/cache
|
||||||
|
key.secret
|
||||||
|
|
11
README.md
11
README.md
|
@ -3,8 +3,15 @@
|
||||||
Software for the K.A.T.I.E.
|
Software for the K.A.T.I.E.
|
||||||
|
|
||||||
## Components
|
## Components
|
||||||
|
### Nightserver
|
||||||
nightserver.py - The central API that the frontend recieves data from. Also serves the frontend itself.
|
nightserver.py - The central API that the frontend recieves data from. Also serves the frontend itself.
|
||||||
|
|
||||||
modules/vitalsd/ - Vitals Daemon. Obtains vitals information and POSTs to nightserver.
|
### Vitalsd
|
||||||
|
- modules/vitalsd/ - Vitals Daemon. Obtains vitals information and POSTs to nightserver.
|
||||||
|
- modules/vitalsd/
|
||||||
|
|
||||||
modules/navigationd/ - Navigation Daemon. Obtains navigation data and POSTs to nightserver.
|
### Navigationd
|
||||||
|
modules/navigationd/ - Navigation Daemon. Obtains navigation data from gpsd and POSTs to nightserver.
|
||||||
|
|
||||||
|
### Musicd
|
||||||
|
modules/musicd/ - Music Daemon. Simply speaking, plays music.
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
export FLASK_APP=nightserver.py
|
export FLASK_APP=nightserver.py
|
||||||
flask run
|
flask run --host=0.0.0.0
|
||||||
|
|
|
@ -31,14 +31,16 @@ def disconnectCyberware():
|
||||||
except:
|
except:
|
||||||
print("Cannot disconnect Cyberware.")
|
print("Cannot disconnect Cyberware.")
|
||||||
|
|
||||||
gpsdData = None
|
def getMapImage(distance, gpsdData):
|
||||||
|
|
||||||
def getMapImage(distance):
|
|
||||||
ox.settings.use_cache = True
|
ox.settings.use_cache = True
|
||||||
|
|
||||||
|
|
||||||
|
# We don't want to send any data if we don't have a fix.
|
||||||
if(gpsdData.lat == 0 and gpsdData.lon == 0):
|
if(gpsdData.lat == 0 and gpsdData.lon == 0):
|
||||||
point = (42.352593, -83.2640164)
|
return
|
||||||
|
#point = (42.352593, -83.2640164)
|
||||||
|
|
||||||
|
point = (gpsdData.lat, gpsdData.lon)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
G = ox.graph_from_point(point, dist=distance, dist_type="bbox", network_type="drive")
|
G = ox.graph_from_point(point, dist=distance, dist_type="bbox", network_type="drive")
|
||||||
|
@ -62,17 +64,20 @@ def getMapImage(distance):
|
||||||
#
|
#
|
||||||
# G = ox.graph_from_bbox(bbox=bbox, network_type="drive_service")
|
# G = ox.graph_from_bbox(bbox=bbox, network_type="drive_service")
|
||||||
|
|
||||||
def sendLocation():
|
def sendLocation(gpsdData):
|
||||||
try:
|
# We don't want to hit the API if we don't have a fix.
|
||||||
#request = requests.post(urlLocation, json={ 'x': gpsdData.lat, 'y': gpsdData.lon, 'z': gpsdData.alt, 'o': gpsdData.track })
|
if(gpsdData.lat != 0 and gpsdData.lon !=0):
|
||||||
request = requests.post(urlLocation, json={ 'x': None, 'y': None, 'z': None, 'o': None, 'uuid': uuid })
|
try:
|
||||||
except:
|
request = requests.post(urlLocation, json={ 'x': gpsdData.lat, 'y': gpsdData.lon, 'z': gpsdData.alt, 'o': None, 'uuid': uuid })
|
||||||
print('Could not contact NightCall')
|
except:
|
||||||
|
print('Could not contact NightCall')
|
||||||
|
|
||||||
def sendMapImage():
|
def sendMapImage():
|
||||||
try:
|
try:
|
||||||
files = { 'image': open(uuid+".png", 'rb') }
|
files = { 'image': open(uuid+".png", 'rb') }
|
||||||
request = requests.post(urlImage, files=files)
|
request = requests.post(urlImage, files=files)
|
||||||
|
except FileNotFoundError: # Occurs if we don't have a fix yet.
|
||||||
|
return
|
||||||
except:
|
except:
|
||||||
print("Could not contact NightCall")
|
print("Could not contact NightCall")
|
||||||
|
|
||||||
|
@ -90,11 +95,10 @@ while continueFlag:
|
||||||
try:
|
try:
|
||||||
gpsdData = gpsd.get_current()
|
gpsdData = gpsd.get_current()
|
||||||
except gpsd.NoFixError:
|
except gpsd.NoFixError:
|
||||||
gpsdData = None
|
print("No GPS fix!")
|
||||||
print("No GPS fix yet! Using default coordinates.")
|
|
||||||
|
|
||||||
getMapImage(1000)
|
getMapImage(1000, gpsdData)
|
||||||
sendLocation()
|
sendLocation(gpsdData)
|
||||||
sendMapImage()
|
sendMapImage()
|
||||||
|
|
||||||
#print(packet.position())
|
#print(packet.position())
|
||||||
|
@ -106,4 +110,8 @@ print("Removing Cyberware")
|
||||||
disconnectCyberware()
|
disconnectCyberware()
|
||||||
|
|
||||||
print("Cleaning up")
|
print("Cleaning up")
|
||||||
os.remove(uuid+".png")
|
|
||||||
|
try:
|
||||||
|
os.remove(uuid+".png")
|
||||||
|
except:
|
||||||
|
print("No minimap image was ever made. GPS probably never had a fix.")
|
||||||
|
|
42
src/modules/vitalsd/aggregatorRecv.py
Normal file
42
src/modules/vitalsd/aggregatorRecv.py
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
import subprocess
|
||||||
|
import requests
|
||||||
|
import sys
|
||||||
|
from flask import jsonify
|
||||||
|
from cyberwareAbs import Cyberware
|
||||||
|
|
||||||
|
class AggregatorRecv(Cyberware):
|
||||||
|
uuid = None
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
print("GadgetBridge Aggregator Reciever started")
|
||||||
|
print("[WARN] GadgetBridge Aggregator not implemented")
|
||||||
|
|
||||||
|
# def sendValue(self, url, jsonRequest):
|
||||||
|
# try:
|
||||||
|
# oldJson = json.loads(jsonRequest)
|
||||||
|
# uuidJson = {'uuid': self.uuid}
|
||||||
|
# oldJson.update(uuidJson)
|
||||||
|
# jsonWithUuid = json.dumps(oldJson)
|
||||||
|
#
|
||||||
|
# request = requests.post(url, json=jsonWithUuid)
|
||||||
|
#
|
||||||
|
# except:
|
||||||
|
# print(self.apiFailMsg)
|
||||||
|
# return 2 # 2 = No API contact.
|
||||||
|
#
|
||||||
|
# if request.status_code > 399:
|
||||||
|
# return 3 # 3 = API refused request.
|
||||||
|
#
|
||||||
|
# if request.status_code > 299:
|
||||||
|
# return 4 # 4 = API encountered an internal error.
|
||||||
|
#
|
||||||
|
# return 0 # 0 = Success
|
||||||
|
|
||||||
|
def sendAll(self):
|
||||||
|
o=0
|
||||||
|
|
||||||
|
def connectCyberware(self):
|
||||||
|
o=0
|
||||||
|
|
||||||
|
def disconnectCyberware(self):
|
||||||
|
o=0
|
23
src/modules/vitalsd/config.ini
Normal file
23
src/modules/vitalsd/config.ini
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
[enabled]
|
||||||
|
Infinitime = false
|
||||||
|
AggregatorRecv = false
|
||||||
|
|
||||||
|
; You should not edit any capabilities variables unless you know what you're doing.
|
||||||
|
[infinitime]
|
||||||
|
capabilities = [
|
||||||
|
"vitals/heartrate",
|
||||||
|
"vitals/steps",
|
||||||
|
"cyberware/battery"
|
||||||
|
]
|
||||||
|
priority = 999
|
||||||
|
|
||||||
|
[aggregatorRecv]
|
||||||
|
capabilities = [
|
||||||
|
"vitals/heartrate",
|
||||||
|
"vitals/steps",
|
||||||
|
"battery",
|
||||||
|
"vitals/bodytemp",
|
||||||
|
"vitals/oxygen",
|
||||||
|
"cyberware/battery"
|
||||||
|
]
|
||||||
|
priority = 0
|
56
src/modules/vitalsd/cyberwareAbs.py
Normal file
56
src/modules/vitalsd/cyberwareAbs.py
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
import subprocess
|
||||||
|
import requests
|
||||||
|
import sys
|
||||||
|
from flask import jsonify
|
||||||
|
from abc import ABC,abstractmethod
|
||||||
|
|
||||||
|
class Cyberware(ABC):
|
||||||
|
# I'll expand this as necessary
|
||||||
|
urlBase = "http://localhost:5000/"
|
||||||
|
ENDPOINTS = {
|
||||||
|
"heartrate":urlBase+"api/vitals/heartrate",
|
||||||
|
"steps":urlBase+"api/vitals/steps",
|
||||||
|
"bodytemp":urlBase+"api/vitals/bodytemp",
|
||||||
|
"oxygen":urlBase+"api/vitals/oxygen",
|
||||||
|
"battery":urlBase+"api/vitals/battery",
|
||||||
|
"add":urlBase+"api/cyberware/add",
|
||||||
|
"remove":urlBase+"api/cyberware/remove"
|
||||||
|
}
|
||||||
|
|
||||||
|
def sendValue(self, url, jsonRequest):
|
||||||
|
try:
|
||||||
|
oldJson = json.loads(jsonRequest)
|
||||||
|
uuidJson = {'uuid': self.uuid}
|
||||||
|
oldJson.update(uuidJson)
|
||||||
|
jsonWithUuid = json.dumps(oldJson)
|
||||||
|
|
||||||
|
request = requests.post(url, json=jsonWithUuid)
|
||||||
|
|
||||||
|
except:
|
||||||
|
print(self.apiFailMsg)
|
||||||
|
return 2 # 2 = No API contact.
|
||||||
|
|
||||||
|
if request.status_code > 399:
|
||||||
|
return 3 # 3 = API refused request.
|
||||||
|
|
||||||
|
if request.status_code > 299:
|
||||||
|
return 4 # 4 = API encountered an internal error.
|
||||||
|
|
||||||
|
return 0 # 0 = Success
|
||||||
|
|
||||||
|
@property
|
||||||
|
@abstractmethod
|
||||||
|
def uuid(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def sendAll(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def connectCyberware(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def disconnectCyberware(self):
|
||||||
|
pass
|
|
@ -1,3 +1,6 @@
|
||||||
|
# TODO: Rewrite this file to use the CyberwareAbs abstract class.
|
||||||
|
# works as-is but man do I have nightmares knowing this file looks like this.
|
||||||
|
|
||||||
import subprocess
|
import subprocess
|
||||||
import requests
|
import requests
|
||||||
import sys
|
import sys
|
||||||
|
@ -160,6 +163,11 @@ class Infinitime:
|
||||||
print(self.apiFailMsg)
|
print(self.apiFailMsg)
|
||||||
self.uuid = None
|
self.uuid = None
|
||||||
|
|
||||||
|
def sendAll(self):
|
||||||
|
self.sendHeartrate()
|
||||||
|
self.sendSteps()
|
||||||
|
self.sendBattery()
|
||||||
|
|
||||||
# while True:
|
# while True:
|
||||||
# try:
|
# try:
|
||||||
# heartrate = getHeartrate()
|
# heartrate = getHeartrate()
|
||||||
|
|
|
@ -1,25 +1,54 @@
|
||||||
from infinitime import Infinitime
|
from infinitime import Infinitime
|
||||||
|
from aggregatorRecv import AggregatorRecv
|
||||||
import time
|
import time
|
||||||
|
import configparser
|
||||||
|
import json
|
||||||
|
|
||||||
pinetimeEnabled = True
|
config = configparser.ConfigParser()
|
||||||
|
config.read('config.ini')
|
||||||
|
|
||||||
|
pinetimeEnabled = config.getboolean('enabled','Infinitime')
|
||||||
|
aggregatorEnabled = config.getboolean('enabled', 'AggregatorRecv')
|
||||||
|
|
||||||
|
enabled = []
|
||||||
|
|
||||||
if(pinetimeEnabled):
|
if(pinetimeEnabled):
|
||||||
pinetime = Infinitime()
|
pinetime = Infinitime()
|
||||||
|
capabilities = json.loads(config.get('infinitime','capabilities'))
|
||||||
|
enabled.append(pinetime)
|
||||||
pinetime.connectCyberware()
|
pinetime.connectCyberware()
|
||||||
|
|
||||||
|
if(aggregatorEnabled):
|
||||||
|
aggregator = AggregatorRecv()
|
||||||
|
capabilities = json.loads(config.get('aggregatorRecv','capabilities'))
|
||||||
|
enabled.append(aggregator)
|
||||||
|
aggregator.connectCyberware()
|
||||||
|
|
||||||
continueFlag = True
|
continueFlag = True
|
||||||
|
|
||||||
|
#while continueFlag:
|
||||||
|
# try:
|
||||||
|
# if(pinetimeEnabled):
|
||||||
|
# pinetime.sendHeartrate()
|
||||||
|
# pinetime.sendSteps()
|
||||||
|
# pinetime.sendHeartrate()
|
||||||
|
#
|
||||||
|
# time.sleep(1)
|
||||||
|
# except KeyboardInterrupt:
|
||||||
|
# print("Stopping vitalsd")
|
||||||
|
# continueFlag = False
|
||||||
|
#
|
||||||
|
#if(pinetimeEnabled):
|
||||||
|
# pinetime.disconnectCyberware()
|
||||||
|
|
||||||
while continueFlag:
|
while continueFlag:
|
||||||
try:
|
try:
|
||||||
if(pinetimeEnabled):
|
for c in enabled:
|
||||||
pinetime.sendHeartrate()
|
c.sendAll()
|
||||||
pinetime.sendSteps()
|
|
||||||
pinetime.sendHeartrate()
|
|
||||||
|
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
print("Stopping vitalsd")
|
print("Stopping vitalsd")
|
||||||
continueFlag = False
|
continueFlag = False
|
||||||
|
|
||||||
if(pinetimeEnabled):
|
for c in enabled:
|
||||||
pinetime.disconnectCyberware()
|
c.disconnectCyberware()
|
||||||
|
|
|
@ -153,7 +153,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------- */
|
/* ------------------------------------- */
|
||||||
/* Below are all center elements - Comms, Popup, and Info */
|
/* Below are all center elements - Interactions (music, messages, etc), Popup, and Info */
|
||||||
|
|
||||||
#centerElements {
|
#centerElements {
|
||||||
flex-grow: 2;
|
flex-grow: 2;
|
||||||
|
@ -162,13 +162,29 @@
|
||||||
/*border: 1px solid #0FF; TODO: Remove this later */
|
/*border: 1px solid #0FF; TODO: Remove this later */
|
||||||
}
|
}
|
||||||
|
|
||||||
#commsPanel {
|
/* Interactions panel (music, messages, etc) */
|
||||||
|
|
||||||
|
#interactionPanel {
|
||||||
width: 20%;
|
width: 20%;
|
||||||
/*flex-grow: 1;*/
|
/*flex-grow: 1;*/
|
||||||
margin-left: 2px;
|
margin-left: 2px;
|
||||||
/*border: 1px solid #F00; TODO: Remove this later */
|
/*border: 1px solid #F00; TODO: Remove this later */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#commsPanel {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: none;
|
||||||
|
border: 1px solid #00F; /* TODO: Remove this later */
|
||||||
|
}
|
||||||
|
|
||||||
|
#musicPanel {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: none;
|
||||||
|
border: 1px solid #0F0; /* TODO: Remove this later */
|
||||||
|
}
|
||||||
|
|
||||||
#popupPanel {
|
#popupPanel {
|
||||||
flex-grow: 2;
|
flex-grow: 2;
|
||||||
margin-left: 2px;
|
margin-left: 2px;
|
||||||
|
@ -226,8 +242,14 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="centerElements">
|
<div id="centerElements">
|
||||||
<div id="commsPanel">
|
<div id="interactionPanel">
|
||||||
<!--<p>Comms</p>-->
|
<div id="commsPanel">
|
||||||
|
<p>Comms</p>
|
||||||
|
</div>
|
||||||
|
<div id="musicPanel">
|
||||||
|
<p>Music</p>
|
||||||
|
</div>
|
||||||
|
<!--<p>Interactions</p>-->
|
||||||
</div>
|
</div>
|
||||||
<div id="popupPanel">
|
<div id="popupPanel">
|
||||||
<!--<p>Popup</p>-->
|
<!--<p>Popup</p>-->
|
||||||
|
|
Loading…
Reference in a new issue