Merge branch 'Development' of https://github.com/Tucan444/Mabasej_Team into Development

This commit is contained in:
Tucan444 2021-05-09 14:38:45 +02:00
commit 402b01ff21
51 changed files with 2423 additions and 984 deletions

169
README.md

@ -1,22 +1,169 @@
# Mabasej_Team # Mabasej_Team
We are working on system, that will help tourists in cities to get information about city more easily. We are working on system, that will help tourists in cities to get information about city more easily.
# Hardware ## Hardware
- Raspberry PI (for now tested only on rpi4. Works on rpi zero too, but it will be slow if more devices are connected) - Raspberry PI (for now tested only on rpi4. Works on rpi zero too, but it will be slow if more devices are connected)
- External/Internal WiFi antena - External/Internal WiFi antena
# Software ## Software
- python 3.9.2 compatible server with basic web interface - python 3.9.2 compatible server with basic web interface
- Kotlin based mobile app - Kotlin based mobile app
# Server ## Install
To run server you need to install Wikispot is in testing stages, but it is possible to install it using our .img file (link coming soon) based on DietPi or custom script.
- hypercorn - "pip install hypercorn"
- fastapi - "pip install fastapi"
- requests - "pip install requests"
- aiofiles - "pip install aiofiles"
then run by command - "hypercorn main:app --bind <IP:port>" | Device | Server compatible | Instalation |
To connect to another rpi you need to edit settings.json with different ID and fill heartbeat table. | :-------------------- | :------------------------------------------------------------------------------------------ | :-----------: |
| Ubuntu (I7, 16GB ram) | :heavy_check_mark: WORKING (Only server) | Manual/script |
| RPI 4b (2GB) | :heavy_check_mark: WORKING | .img/script |
| RPI 400 (4GB) | :grey_question: Untested. Should work. | .img/script |
| RPI 3b+ | :grey_question: Untested. Should work. | .img/script |
| RPI zero w | :white_check_mark: Working with fewer devices (Only server. No AP, Computer vision) | .img/script |
| RPI 2 | :question: Untested. | :x: |
| RPI | :question: Untested. | :x: |
This is not finished product
### Fresh istall (.img) Only RPI
login credentials
> login: dietpi
> password: WikiSpot2021
requirements:
1. WikiSpot image file (download: *soon*)
2. MicroSd card (recommended: >=16GB, :exclamation: ALL DATA STORED ON SD CARD WILL BE FORMATED :exclamation:)
3. BalenaEtcher (or another sd card flasher) *link:* https://www.balena.io/etcher/
4. SD card reader
Install:
1. Download all required files (wikispot.img and balenaetcher) and install BalenaEtcher
2. Insert SD card into computer/reader, open BalenaEtcher -> chose Flash from file -> chose downloaded wikispot.img -> Select your sd in *Select target* -> Flash!
3. :exclamation: WINDOWS will show unformated drive. Cancel it. It is because of uncompatible format for windows :exclamation:
4. After flashing open partition *boot* (should apear as USB), find file *dietpi.txt* and open it in text editor.
- Accept license by changing `AUTO_SETUP_ACCEPT_LICENSE=0` to `AUTO_SETUP_ACCEPT_LICENSE=1`
- Change name of WikiSpot `AUTO_SETUP_NET_HOSTNAME=WikiSpot-CHANGE_ME` by changing only *CHANGE_ME* or leave *CHANGE_ME* for random number name *WikiSpot-54346
- You can set static ip address by changing `AUTO_SETUP_NET_USESTATIC=0` to `AUTO_SETUP_NET_USESTATIC=1` And entering your setting into required lines.
- If you want to use computer vision plugin with rpi camera set `ENABLE_COMPUTER_VISION_PLUGIN=0` to `ENABLE_COMPUTER_VISION_PLUGIN=1` (*recommended only on RPI4)
- If you want to use RPI as access point to WikiSpot change `#AUTO_SETUP_INSTALL_SOFTWARE_ID=60` to `AUTO_SETUP_INSTALL_SOFTWARE_ID=60`
- *wifi setup in testing*
5. :grey_exclamation:For advanced users:grey_exclamation: You can now change contens of WikiSpot server in `/boot/WikiSpot`according to an example in server filesystem
6. Eject sd card from computer, insert it in Raspberry Pi and power it on. :bangbang:Raspberry Pi needs to be connected to intenet via Ethernet (*wifi coming soon*) othervise the setup will crash.
7. The setup will take approximately 25-40 min (RPI 4b (2gb) and 70 mb download speed)
8. Done you can start using WikiSpot and edit contents of WikiSpot with our app (*coming soon*)
### Script install
*coming soon*
### Manual install
*coming soon*
## Server filesystem
```
└── test_directory
├── cache # files forwarded from another servers to client
├── engine.py # engine for server (log, recovery, update)
├── files # content of WikiSpot server
│   └── test.jpg
├── filesystem.json # data settings of server (name, description, files)
├── main.py # main server file
├── plugins # plugins file
│   └── computer_vision # oficial WikiSpot computer vision plugin for RPI 4
│   ├── MobileNetSSD_deploy.caffemodel
│   ├── MobileNetSSD_deploy.prototxt
│   └── com_vision.py
├── run.py # start script for server
├── settings.json # settings (log, debug, connected WikiSpots, cache size,...)
├── system.py # update and clean script
└── version.json # version of WikiSpot
```
### filesystem
```
{
"ID": 0, # ID of WikiSpots, Needs to be different, because network will crash
"location": "25.997417761947318, -97.15738221291177", # Location of WikiSpot server copied from google maps
"description": {
"title": "WikiSpot demo", # Name of WikiSpot server (swiming pool, school, ...)
"description_s": "This is showcase of WikiSpot", # Short description showed on web/app in list of servers
"description_l": "This will show after opening server in app", # Long description showed after opening the server in web/app
"photo_s": "test.jpg", # Small image showed on web/app in list of servers
"photo_b": "test.png" # Big image showed after opening the server in web/app
},
"files": [ # files on server in /files that will be mediated to the web/app
{
"name": "test", # Name of the file, without spaces. App will change "_" to spaces
"format": ".jpg", # Format of the file
"description": "This is test file" # Description showed next to the file
}
]
}
```
To manualy add new file to server (on setup or via ssh) add file to `server_directory/files`
and add record for file into `files` list in `filesystem.json`. :exclamation:do not forget "," after last record:exclamation:
```
{
"name": "new_file_name",
"format": ".txt",
"description": "This is how you add new file"
}
```
### settings.json
```
{
"time_to_heartbeat": 20, # Time to ping of another online servers in seconds
"time_to_heartbeat_offline": 25, # Time to ping of another offline servers in seconds
"save_table": true, # Save connected servers to reconnect after restart
"time_to_save": 60, # Time to save server in seconds
"max_mess": 20, # Maximum messages stored in RAM
"cache_size_mb": 1000, # Maximum size of cache directory in mb
"clear_cache_on_startup": false, # Remove contents of cache on startup (slower first downloads)
"log": { # Log settings
"save_error": true, # Save errors into log.txt
"print_error": true, # Print errors into console (if running as service into linux log)
"save_warning": true, # Save warnings into log.txt
"print_warning": true, # Print warnings into console (if running as service into linux log)
"save_message": false, # Save messages (new server, etc. not messages from clients) into log.txt
"print_message": true, # Print messages into console (if running as service into linux log)
"enable_debug": false # Enable debug into console (if running as service into linux log)
},
"heartbeat_table": { # Saved servers
"ID": [],
"IP": [],
"location": [],
"file_system": [],
"last_heartbeat": []
}
}
```
If you want to manually add server on first setup or via ssh fill heartbeat table like this.
```
"heartbeat_table": { # Saved servers
"ID": [1], # ID of server as integer (number)
"IP": ["192.168.1.2"], # IP of server as string
"location": [""], # Empty string as placeholder. location will be downloaded after first connection
"file_system": [""], # Empty string as placeholder. filesystem will be downloaded after first connection
"last_heartbeat": [10] # After how many seconds will server try to connect for the first time
}
```
:bangbang:If the server will be offline for long time (heartbeat + offline heartbeat) it will be removed from heartbeat table. If the save function is disabled server will trying to connect after restart:bangbang:
*This is not finished product*

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/../.." vcs="Git" />
</component>
</project>

Binary file not shown.

@ -0,0 +1,22 @@
Vybavenie
Šatňa - áno
Vlastné parkovisko - áno
Televízor - áno
Pre rodiny s deťmi
Detské stoličky - áno
detský kútik - áno
Služby
Čapované pivo - áno
Organizovanie spoločenských podujatí áno
Koktail bar - áno
Kontakt
Adresa: Dlhá 58 , 095 01 Senica
Telefón: +421
Email: restauracia.kojda@gmail.com

Binary file not shown.

After

Width:  |  Height:  |  Size: 315 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

@ -0,0 +1,17 @@
Otváracie hodiny:
PON-PIA: 09:00 - 17:00
SOB: zatvorené
NED: 10:00-16:00
13:00-13:30 (obedná prestávka)
- Predaj doplnkového tovaru
- Výmena peňazí
- Telekomunikačné služby
- predplatné novín a časopisov
Kontakt
Adresa: Športovcov 7212, 017 01 Považská Bystrica
Telefón: 0918 221 189
email: slovenska.posta@gmail.com

Binary file not shown.

After

Width:  |  Height:  |  Size: 304 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

@ -0,0 +1,23 @@
Služby
- Plavecký bazén
- Relaxačný bazén
- Detský bazén
Sauna
- fínska
- ruská
- turecká
- bylinková
- infra sauna
- Masáže
Kontakt
Adresa: Mládežnícka 12,
017 01 Považská Bystrica
Telefón: 032/221 52 97

Binary file not shown.

After

Width:  |  Height:  |  Size: 158 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 474 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

@ -0,0 +1,18 @@
Služby na stanici:
- Bezplatné parkovanie
- Poistenie na počkanie
- Predaj cestovných lístkov
- Predaj miesteniek
- Rezervácie
- Predaj žrebov Niké
Kontakt
Adresa: Zámostie, 017 01 Považská Bystrica
Telefón
Slovensko: 18 188
Zo zahraničia: +421 24 28 54 182
info@slovakrail.sk

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

@ -0,0 +1,24 @@
{
"ID": 0,
"location": "49.14178021389778,18.353783098441415",
"description": {
"title": "Reštaurácia pod slivkou",
"description_s": "Otvorené",
"description_l": "Otváracie hodiny:\nPON-PIA: 09:00 - 22:00\nSOB: zatvorené\nNED: 14:00-21:00",
"photo_s": "restaurant_out.jpg",
"photo_b": "restaurant_in.jpg",
"email": "restauracia.podslivkou@gmail.com",
"phone_number": "0928229120"
},
"files": [
{
"name": "Podrobnosti",
"format": ".txt",
"description": "Vybavenie, služby a kontakt"
}, {
"name": "Jedálny lístok",
"format": ".pdf",
"description": ""
}
]
}

@ -0,0 +1,24 @@
{
"ID": 1,
"location": "49.095721799569304, 18.47399399775766",
"description": {
"title": "Slovenská pošta",
"description_s": "Otvorené",
"description_l": "Otváracie hodiny:\nPON-PIA: 09:00 - 17:00\nSOB: zatvorené\nNED: 10:00-16:00",
"photo_s": "post_out.jpg",
"photo_b": "post_in.jpg",
"email": "slovenska.posta@gmail.com",
"phone_number": "0918221189"
},
"files1": [
{
"name": "Podrobnosti",
"format": ".txt",
"description": ""
}, {
"name": "Cenník",
"format": ".pdf",
"description": ""
}
]
}

@ -0,0 +1,24 @@
{
"ID": 2,
"location": "49.14437583832675, 18.466946907073503",
"description": {
"title": "Mestská plaváreň",
"description_s": "Otvorené",
"description_l": "Otvorené nonstop\nOtváracie doby sa počas sviatkov môžu líšiť",
"photo_s": "plavaren_out.jpg",
"photo_b": "plavaren_in.jpg",
"email": "",
"phone_number": "0322215297"
},
"files2": [
{
"name": "Služby a kontakt",
"format": ".txt",
"description": ""
}, {
"name": "Fotogaléria a cenník",
"format": ".pdf",
"description": ""
}
]
}

@ -0,0 +1,24 @@
{
"ID": 3,
"location": "49.10101907820781, 18.440001048091226",
"description": {
"title": "Považsko Bystrické Múzeum",
"description_s": "Otvorené",
"description_l": "Otváracie hodiny:\nUT-PIA: 08:00 - 16:00",
"photo_s": "muzeum_out.jpg",
"photo_b": "muzeum_in.jpg",
"email": "pbmuzeum@gmail.com",
"phone_number": "0971294689"
},
"files3": [
{
"name": "Cenník",
"format": ".pdf",
"description": ""
}, {
"name": "Náhľad",
"format": ".pdf",
"description": "Nahľiadnite do expozície múzea"
}
]
}

@ -0,0 +1,24 @@
{
"ID": 4,
"location": "49.12230758939453, 18.43195784744756",
"description": {
"title": "Železničná stanica",
"description_s": "Otvorené",
"description_l": "Otváracie hodiny:\nnonstop",
"photo_s": "zeleznicna_stanica_out.jpg",
"photo_b": "zeleznicna_stanica_in.jpg",
"email": "info@slovakrail.sk",
"phone_number": ""
},
"files4": [
{
"name": "Podrobnosti",
"format": ".txt",
"description": ""
}, {
"name": "Zľavy",
"format": ".pdf",
"description": ""
}
]
}

@ -1,58 +0,0 @@
import requests, json, uuid
class Server:
def __init__(self, server_ip="0.0.0.0"):
self.device_id = None
self.server = None
self.client_id = uuid.uuid4().hex[24:]
try:
r = requests.get(f"http://{server_ip}:8000/discovery")
if r.text.strip('"') == "Success":
self.server = server_ip
rr = requests.get(f"http://{server_ip}:8000/devices_list")
self.device_id = dict(rr.json()[0])["connected_id"]
except Exception as error:
print(f"Program experienced a ERROR\nError: {error}")
self.server = None
def get_sensors(self, server_id=None):
if not server_id:
cache = self.device_id
else:
cache = server_id
if self.server:
r = requests.get(f"http://{self.server}:8000/{cache}/sensors")
return dict(r.json())
else:
raise Exception("Module was not inicialized/server was not found")
def update_sensors(self, name, value, ID=None):
if not name and not value:
raise Exception("Invalid values were passed")
r = requests.post(f"http://{self.server}:8000/{ID if ID else self.device_id}/update_sensor")
return r.text
def update_server(self, version, update_all=True):
if update_all:
r = requests.get(f"http://{self.server}:8000/admin/get/update-{version}")
else:
r = requests.get(f"http://{self.server}:8000/admin/get/update_one-{version}")
return r.text
def get_versions(self):
return requests.get(f"http://{self.server}:8000/admin/get/get_updates").text
def post_message(self, message):
r = requests.post(f"http://{self.server}:8000/messages/post", json={"m_sender": self.client_id,
"message": str(message)})
return r.text
def get_messages(self, timestamp=""):
r = requests.get(f"http://{self.server}:8000/messages/get", data={"timestamp": timestamp})
return r.text
def upload_file(self, file_path, save_path):
with open(file_path, "r") as cache:
r = requests.get(f"http://{self.server}:8000/messages/get", files={"uploaded_file": cache, "patch": save_path})
return r.text

BIN
server/cache/1/test.jpg vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 354 KiB

Binary file not shown.

@ -1,198 +0,0 @@
%PDF-1.3
%âãÏÓ
1 0 obj
<<
/Type /Catalog
/Outlines 2 0 R
/Pages 3 0 R
>>
endobj
2 0 obj
<<
/Type /Outlines
/Count 0
>>
endobj
3 0 obj
<<
/Type /Pages
/Count 2
/Kids [ 4 0 R 6 0 R ]
>>
endobj
4 0 obj
<<
/Type /Page
/Parent 3 0 R
/Resources <<
/Font <<
/F1 9 0 R
>>
/ProcSet 8 0 R
>>
/MediaBox [0 0 612.0000 792.0000]
/Contents 5 0 R
>>
endobj
5 0 obj
<< /Length 1074 >>
stream
2 J
BT
0 0 0 rg
/F1 0027 Tf
57.3750 722.2800 Td
( A Simple PDF File ) Tj
ET
BT
/F1 0010 Tf
69.2500 688.6080 Td
( This is a small demonstration .pdf file - ) Tj
ET
BT
/F1 0010 Tf
69.2500 664.7040 Td
( just for use in the Virtual Mechanics tutorials. More text. And more ) Tj
ET
BT
/F1 0010 Tf
69.2500 652.7520 Td
( text. And more text. And more text. And more text. ) Tj
ET
BT
/F1 0010 Tf
69.2500 628.8480 Td
( And more text. And more text. And more text. And more text. And more ) Tj
ET
BT
/F1 0010 Tf
69.2500 616.8960 Td
( text. And more text. Boring, zzzzz. And more text. And more text. And ) Tj
ET
BT
/F1 0010 Tf
69.2500 604.9440 Td
( more text. And more text. And more text. And more text. And more text. ) Tj
ET
BT
/F1 0010 Tf
69.2500 592.9920 Td
( And more text. And more text. ) Tj
ET
BT
/F1 0010 Tf
69.2500 569.0880 Td
( And more text. And more text. And more text. And more text. And more ) Tj
ET
BT
/F1 0010 Tf
69.2500 557.1360 Td
( text. And more text. And more text. Even more. Continued on page 2 ...) Tj
ET
endstream
endobj
6 0 obj
<<
/Type /Page
/Parent 3 0 R
/Resources <<
/Font <<
/F1 9 0 R
>>
/ProcSet 8 0 R
>>
/MediaBox [0 0 612.0000 792.0000]
/Contents 7 0 R
>>
endobj
7 0 obj
<< /Length 676 >>
stream
2 J
BT
0 0 0 rg
/F1 0027 Tf
57.3750 722.2800 Td
( Simple PDF File 2 ) Tj
ET
BT
/F1 0010 Tf
69.2500 688.6080 Td
( ...continued from page 1. Yet more text. And more text. And more text. ) Tj
ET
BT
/F1 0010 Tf
69.2500 676.6560 Td
( And more text. And more text. And more text. And more text. And more ) Tj
ET
BT
/F1 0010 Tf
69.2500 664.7040 Td
( text. Oh, how boring typing this stuff. But not as boring as watching ) Tj
ET
BT
/F1 0010 Tf
69.2500 652.7520 Td
( paint dry. And more text. And more text. And more text. And more text. ) Tj
ET
BT
/F1 0010 Tf
69.2500 640.8000 Td
( Boring. More, a little more text. The end, and just as well. ) Tj
ET
endstream
endobj
8 0 obj
[/PDF /Text]
endobj
9 0 obj
<<
/Type /Font
/Subtype /Type1
/Name /F1
/BaseFont /Helvetica
/Encoding /WinAnsiEncoding
>>
endobj
10 0 obj
<<
/Creator (Rave \(http://www.nevrona.com/rave\))
/Producer (Nevrona Designs)
/CreationDate (D:20060301072826)
>>
endobj
xref
0 11
0000000000 65535 f
0000000019 00000 n
0000000093 00000 n
0000000147 00000 n
0000000222 00000 n
0000000390 00000 n
0000001522 00000 n
0000001690 00000 n
0000002423 00000 n
0000002456 00000 n
0000002574 00000 n
trailer
<<
/Size 11
/Root 1 0 R
/Info 10 0 R
>>
startxref
2714
%%EOF

Binary file not shown.

Before

Width:  |  Height:  |  Size: 76 KiB

@ -1 +1 @@
toto je test číslo 1 zo serveru s ID 2 toto je test číslo 1

@ -1 +0,0 @@
toto je test n. 2 zo serveru ID2

@ -1,10 +1,10 @@
{ {
"ID": 0, "ID": 0,
"location": "49.14178021389778,18.353783098441415", "location": "25.997417761947318, -97.15738221291177",
"description": { "description": {
"title": "legionrpi", "title": "WikiSpot-demo",
"description_s": "kr\u00e1tky popis, ktor\u00fd bude zobrazen\u00fd iba v n\u00e1hladovom okne", "description_s": "Krátky popis",
"description_l": "dlh\u0161\u00ed popis zariadenia, ktor\u00fd bude zobrazen\u00fd po otvoren\u00ed", "description_l": "Dlhší popis",
"photo_s": "test.jpg", "photo_s": "test.jpg",
"photo_b": "test.png" "photo_b": "test.png"
}, },
@ -12,12 +12,12 @@
{ {
"name": "test", "name": "test",
"format": ".jpg", "format": ".jpg",
"description": "toto je jpg test file" "description": "This is jpg test file"
}, },
{ {
"name": "test2", "name": "test",
"format": ".txt", "format": ".txt",
"description": "toto je txt test file" "description": "This is txt test file"
} }
] ]
} }

@ -1,202 +1,3 @@
2021-03-21 12:33:11.947538 -> Warning: 192.168.1.232 disconnected/is not available 2021-05-08 16:11:06.311275 -> Warning: 192.168.1.231 disconnected/is not available
2021-03-24 09:47:07.677185 -> Warning: 192.168.1.232 disconnected/is not available 2021-05-08 16:11:37.323462 -> Warning: 192.168.1.231 disconnected/is not available
2021-03-24 10:51:12.802174 -> Warning: 192.168.1.232 disconnected/is not available
2021-03-24 10:51:12.804164 -> Warning: 192.168.1.231 disconnected/is not available
2021-03-24 12:20:17.717820 -> Warning: 192.168.1.231 disconnected/is not available
2021-03-24 12:20:18.728113 -> Warning: 192.168.1.232 disconnected/is not available
2021-04-06 17:47:36.579990 -> Warning: 192.168.1.232 disconnected/is not available
2021-04-06 18:01:09.637683 -> Warning: 192.168.1.232 disconnected/is not available
2021-04-06 18:06:27.367910 -> Warning: 192.168.1.232 failed to update. Manual update may be needed for proper working of network.
Response from server: {"detail":"Not Found"}
2021-04-06 18:09:14.702582 -> Warning: 192.168.1.232 failed to update. Manual update may be needed for proper working of network.
Response from server: {"detail":"Not Found"}
2021-04-06 18:09:44.558742 -> Warning: 192.168.1.232 failed to update. Manual update may be needed for proper working of network.
Response from server: {"detail":"Not Found"}
2021-04-06 18:11:19.482976 -> Warning: 192.168.1.232 failed to update. Manual update may be needed for proper working of network.
Response from server: {"detail":"Not Found"}
2021-04-06 18:21:00.445053 -> Warning: 192.168.1.232 failed to update. Manual update may be needed for proper working of network.
Response from server: Internal Server Error
2021-04-06 18:21:00.468768 -> Warning: 192.168.1.231 failed to update. Manual update may be needed for proper working of network.
Response from server: Internal Server Error
2021-04-06 18:26:26.230043 -> Warning: 192.168.1.232 failed to update. Manual update may be needed for proper working of network.
Response from server: "Version not found.\n"
2021-04-06 18:26:26.765624 -> Warning: 192.168.1.231 failed to update. Manual update may be needed for proper working of network.
Response from server: "Version not found.\n"
2021-04-06 18:26:46.326513 -> Warning: 192.168.1.232 failed to update. Manual update may be needed for proper working of network.
Response from server: "Version not found.\n"
2021-04-06 18:26:46.857832 -> Warning: 192.168.1.231 failed to update. Manual update may be needed for proper working of network.
Response from server: "Version not found.\n"
2021-04-06 18:27:17.853160 -> Warning: 192.168.1.232 failed to update. Manual update may be needed for proper working of network.
Response from server: "Version not found.\n"
2021-04-06 18:27:18.393648 -> Warning: 192.168.1.231 failed to update. Manual update may be needed for proper working of network.
Response from server: "Version not found.\n"
2021-04-06 18:28:32.760504 -> Warning: 192.168.1.232 failed to update. Manual update may be needed for proper working of network.
Response from server: "Version not found.\n"
2021-04-06 18:28:33.303332 -> Warning: 192.168.1.231 failed to update. Manual update may be needed for proper working of network.
Response from server: "Version not found.\n"
2021-04-06 18:28:47.795564 -> Warning: 192.168.1.232 disconnected/is not available
2021-04-06 18:29:38.864951 -> Warning: 192.168.1.232 disconnected/is not available
2021-04-06 18:30:21.991616 -> Warning: 192.168.1.232 failed to update. Manual update may be needed for proper working of network.
Response from server: "Download succefull\nExtracting update\nupdate to 0.6 was succefull.\n"
2021-04-06 18:30:22.828559 -> Warning: 192.168.1.231 failed to update. Manual update may be needed for proper working of network.
Response from server: "Download succefull\nExtracting update\nupdate to 0.6 was succefull.\n"
2021-04-06 18:38:39.034010 -> Warning: 192.168.1.232 failed to update. Manual update may be needed for proper working of network.
Response from server: "SUCCESS\nUpdate from version {'version': '0.6', 'id': 4, 'url': 'https://raw.githubusercontent.com/UntriexTv/test_directory/main/ver.json'} to 0.6 was sucesfull\n"
2021-04-06 18:38:39.846078 -> Warning: 192.168.1.231 failed to update. Manual update may be needed for proper working of network.
Response from server: "SUCCESS\nUpdate from version {'version': '0.6', 'id': 4, 'url': 'https://raw.githubusercontent.com/UntriexTv/test_directory/main/ver.json'} to 0.6 was sucesfull\n"
2021-04-06 18:38:43.579251 -> Warning: 192.168.1.231 disconnected/is not available
2021-04-06 18:41:20.200515 -> Warning: 192.168.1.232 failed to update. Manual update may be needed for proper working of network.
Response from server: "SUCCESS\nUpdate from version {'0.1': {'change_list': 'this is only initial release for testing purpose', 'id': 2}, '0.5': {'change_list': 'fist working release', 'id': 3}, '0.6': {'change_list': 'normal update', 'id': 4}} to 0.6 was sucesfull\n"
2021-04-06 18:41:21.012333 -> Warning: 192.168.1.231 failed to update. Manual update may be needed for proper working of network.
Response from server: "SUCCESS\nUpdate from version {'0.1': {'change_list': 'this is only initial release for testing purpose', 'id': 2}, '0.5': {'change_list': 'fist working release', 'id': 3}, '0.6': {'change_list': 'normal update', 'id': 4}} to 0.6 was sucesfull\n"
2021-04-06 18:43:14.079603 -> Warning: 192.168.1.232 failed to update. Manual update may be needed for proper working of network.
Response from server: "SUCCESS\nUpdate from version 0.6 to 0.6 was sucesfull\n"
2021-04-06 18:43:14.908686 -> Warning: 192.168.1.231 failed to update. Manual update may be needed for proper working of network.
Response from server: "SUCCESS\nUpdate from version 0.6 to 0.6 was sucesfull\n"
2021-04-06 18:44:45.325212 -> Warning: 192.168.1.232 failed to update. Manual update may be needed for proper working of network.
Response from server: {"detail":"Not Found"}
2021-04-06 18:44:45.334610 -> Warning: 192.168.1.231 failed to update. Manual update may be needed for proper working of network.
Response from server: {"detail":"Not Found"}
2021-04-06 18:44:51.128403 -> Warning: 192.168.1.232 failed to update. Manual update may be needed for proper working of network.
Response from server: {"detail":"Not Found"}
2021-04-06 18:44:51.135988 -> Warning: 192.168.1.231 failed to update. Manual update may be needed for proper working of network.
Response from server: {"detail":"Not Found"}
2021-04-06 18:45:13.073433 -> Warning: 192.168.1.232 failed to update. Manual update may be needed for proper working of network.
Response from server: "SUCCESS\nUpdate from version 0.6 to 0.6 was sucesfull\n"
2021-04-06 18:45:13.894493 -> Warning: 192.168.1.231 failed to update. Manual update may be needed for proper working of network.
Response from server: "SUCCESS\nUpdate from version 0.6 to 0.6 was sucesfull\n"
2021-04-06 18:46:42.900283 -> Warning: 192.168.1.232 failed to update. Manual update may be needed for proper working of network.
Response from server: "SUCCESS\nUpdate from version 0.6 to 0.6 was sucesfull\n"
2021-04-06 18:46:43.720053 -> Warning: 192.168.1.231 failed to update. Manual update may be needed for proper working of network.
Response from server: "SUCCESS\nUpdate from version 0.6 to 0.6 was sucesfull\n"
2021-04-06 18:47:20.543756 -> Warning: 192.168.1.232 failed to update. Manual update may be needed for proper working of network.
Response from server: "SUCCESS\nUpdate from version 0.6 to 0.6 was sucesfull\n"
2021-04-06 18:47:21.533385 -> Warning: 192.168.1.231 failed to update. Manual update may be needed for proper working of network.
Response from server: "SUCCESS\nUpdate from version 0.6 to 0.6 was sucesfull\n"
2021-04-06 18:48:44.524464 -> Warning: 192.168.1.232 failed to update. Manual update may be needed for proper working of network.
Response from server: "SUCCESS\nUpdate from version 0.6 to 0.6 was sucesfull\n"
2021-04-06 18:48:45.362610 -> Warning: 192.168.1.231 failed to update. Manual update may be needed for proper working of network.
Response from server: "SUCCESS\nUpdate from version 0.6 to 0.6 was sucesfull\n"
2021-04-06 18:49:28.460321 -> Warning: 192.168.1.232 failed to update. Manual update may be needed for proper working of network.
Response from server: "SUCCESS\nUpdate from version 0.6 to 0.6 was sucesfull\n"
2021-04-06 18:49:29.387142 -> Warning: 192.168.1.231 failed to update. Manual update may be needed for proper working of network.
Response from server: "SUCCESS\nUpdate from version 0.6 to 0.6 was sucesfull\n"
2021-04-06 18:52:52.010837 -> Warning: 192.168.1.231 disconnected/is not available
2021-04-06 18:53:06.029220 -> Warning: 192.168.1.232 disconnected/is not available
2021-04-06 19:52:34.214066 -> Warning: Device Address(host='10.42.0.238', port=18381) is creating new sensor data.
SENSOR: ['vlhkost', '40']
2021-04-06 20:58:51.194511 -> Warning: Address(host='10.42.0.238', port=11244) created new sensor.
SENSOR: name='Teplota' value='18'
2021-04-06 20:58:52.311838 -> Warning: Address(host='10.42.0.238', port=8118) created new sensor.
SENSOR: name='Vlhkost' value='52'
2021-04-06 21:00:22.844916 -> Warning: Address(host='10.42.0.238', port=9199) created new sensor.
SENSOR: name='Teplota' value='27'
2021-04-06 21:00:23.915833 -> Warning: Address(host='10.42.0.238', port=15482) created new sensor.
SENSOR: name='Vlhkost' value='95'
2021-04-06 21:01:04.874694 -> Warning: Address(host='10.42.0.238', port=4606) created new sensor.
SENSOR: name='Teplota' value='24'
2021-04-06 21:01:06.020948 -> Warning: Address(host='10.42.0.238', port=16111) created new sensor.
SENSOR: name='Vlhkost' value='95'
2021-04-06 21:02:56.676046 -> Warning: Address(host='10.42.0.238', port=1280) created new sensor.
SENSOR: name='Teplota' value='20'
2021-04-06 21:02:57.773619 -> Warning: Address(host='10.42.0.238', port=12034) created new sensor.
SENSOR: name='Vlhkost' value='91'
2021-04-07 14:07:15.258217 -> Warning: Address(host='10.42.0.238', port=32353) created new sensor.
SENSOR: name='Teplota' value='19'
2021-04-07 14:07:16.454490 -> Warning: Address(host='10.42.0.238', port=19858) created new sensor.
SENSOR: name='Vlhkost' value='46'
2021-04-07 14:17:42.961164 -> Warning: Address(host='10.42.0.238', port=4696) created new sensor.
SENSOR: name='Teplota' value='20'
2021-04-07 14:17:44.114338 -> Warning: Address(host='10.42.0.238', port=4387) created new sensor.
SENSOR: name='Vlhkost' value='42'
2021-04-07 14:18:25.886229 -> Warning: 192.168.1.232 disconnected/is not available
2021-04-07 14:22:13.260725 -> ERROR: Sensor data download from 1 failed.
ERROR: 1 is not in list
2021-04-07 14:22:42.995956 -> ERROR: Sensor data download from 1 failed.
ERROR: 1 is not in list
2021-04-07 17:06:13.637610 -> ERROR: Sensor data download from 25 failed.
ERROR: 25 is not in list
2021-04-07 17:16:09.500542 -> Warning: test on server 192.168.1.231 is changed.
2021-04-07 17:24:05.379288 -> Warning: Address(host='10.42.0.238', port=25175) created new sensor.
SENSOR: name='Teplota' value='20'
2021-04-07 17:24:06.475344 -> Warning: Address(host='10.42.0.238', port=5919) created new sensor.
SENSOR: name='Vlhkost' value='46'
2021-04-07 17:34:29.681729 -> Warning: Address(host='10.42.0.238', port=8767) created new sensor.
SENSOR: name='Teplota' value='20'
2021-04-07 17:34:30.857047 -> Warning: Address(host='10.42.0.238', port=19458) created new sensor.
SENSOR: name='Vlhkost' value='46'
2021-04-07 17:35:06.210117 -> Warning: Address(host='10.42.0.238', port=15677) created new sensor.
SENSOR: name='Teplota' value='20'
2021-04-07 17:35:07.332588 -> Warning: Address(host='10.42.0.238', port=27433) created new sensor.
SENSOR: name='Vlhkost' value='46'
2021-04-07 17:36:02.490752 -> Warning: Address(host='10.42.0.238', port=29010) created new sensor.
SENSOR: name='Teplota' value='20'
2021-04-07 17:36:03.561727 -> Warning: Address(host='10.42.0.238', port=26279) created new sensor.
SENSOR: name='Vlhkost' value='46'
2021-04-07 17:39:30.650731 -> Warning: Address(host='10.42.0.238', port=26716) created new sensor.
SENSOR: name='Teplota' value='20'
2021-04-07 17:39:31.746802 -> Warning: Address(host='10.42.0.238', port=11238) created new sensor.
SENSOR: name='Vlhkost' value='46'
2021-04-07 19:03:34.951363 -> Warning: Address(host='10.42.0.238', port=19388) created new sensor.
SENSOR: name='Teplota' value='20'
2021-04-07 19:03:36.076556 -> Warning: Address(host='10.42.0.238', port=24582) created new sensor.
SENSOR: name='Vlhkost' value='46'
2021-04-07 20:03:53.809025 -> Warning: Address(host='10.42.0.238', port=30182) created new sensor.
SENSOR: name='Vlhkost' value='46'
2021-04-14 12:55:05.505789 -> ERROR: Sensor data download from 1 failed.
ERROR: 1 is not in list
2021-04-14 13:04:30.181791 -> Warning: Address(host='192.168.1.99', port=54888) created new sensor.
SENSOR: name='sensor1' value='test'
2021-04-14 13:04:36.780037 -> Warning: Address(host='192.168.1.99', port=54904) created new sensor.
SENSOR: name='sensor2' value='1234'
2021-04-14 13:06:59.405575 -> Warning: Address(host='192.168.1.99', port=54974) created new sensor.
SENSOR: name='sensor2' value='1234'
2021-04-14 14:09:58.696666 -> Warning: Address(host='192.168.1.99', port=58182) created new sensor.
SENSOR: name='sensor1' value='test'
2021-04-14 14:10:06.190377 -> Warning: Address(host='192.168.1.99', port=58192) created new sensor.
SENSOR: name='sensor2' value='123456789'
2021-04-22 10:15:53.540044 -> Warning: Address(host='192.168.1.99', port=43642) created new sensor.
SENSOR: name='test1' value='juhuu'
2021-04-22 10:16:02.865022 -> Warning: Address(host='192.168.1.99', port=43644) created new sensor.
SENSOR: name='test2' value='eeeh'
2021-04-23 11:22:54.684617 -> Warning: 192.168.1.231 disconnected/is not available
2021-04-23 11:36:58.295015 -> Warning: 192.168.1.231 disconnected/is not available
2021-04-23 18:13:09.497747 -> Warning: Address(host='192.168.1.28', port=45062) created new sensor.
SENSOR: name='teplota' value='26°C'
2021-04-23 20:25:12.224311 -> ERROR: Address(host='192.168.1.28', port=48898) tried to access file (_[{(V,a,r,i,a,b,l,e, ,m,i,s,s,i,n,g)}]_) on id 1 that does not exist.
2021-04-23 20:25:14.287622 -> ERROR: Address(host='192.168.1.28', port=48898) tried to access file (_[{(V,a,r,i,a,b,l,e, ,m,i,s,s,i,n,g)}]_) on id 1 that does not exist.
2021-04-24 11:54:17.948411 -> ERROR: Sensor data download from 1 failed.
ERROR: 1 is not in list
2021-04-24 11:54:21.952522 -> ERROR: Sensor data download from 1 failed.
ERROR: 1 is not in list
2021-04-24 18:38:26.095820 -> ERROR: Address(host='192.168.1.7', port=32928) tried to access file (_[{(V,a,r,i,a,b,l,e, ,m,i,s,s,i,n,g)}]_) on id 1 that does not exist.
2021-04-24 18:38:28.128341 -> ERROR: Address(host='192.168.1.7', port=33038) tried to access file (_[{(V,a,r,i,a,b,l,e, ,m,i,s,s,i,n,g)}]_) on id 1 that does not exist.
2021-04-24 18:41:06.944584 -> ERROR: Address(host='192.168.1.7', port=33612) tried to access file (_[{(V,a,r,i,a,b,l,e, ,m,i,s,s,i,n,g)}]_) on id 1 that does not exist.
2021-04-24 18:41:08.942270 -> ERROR: Address(host='192.168.1.7', port=33612) tried to access file (_[{(V,a,r,i,a,b,l,e, ,m,i,s,s,i,n,g)}]_) on id 1 that does not exist.
2021-04-24 18:41:08.961718 -> ERROR: Address(host='192.168.1.7', port=33612) tried to access file (_[{(V,a,r,i,a,b,l,e, ,m,i,s,s,i,n,g)}]_) on id 1 that does not exist.
2021-04-24 18:41:11.001168 -> ERROR: Address(host='192.168.1.7', port=33996) tried to access file (_[{(V,a,r,i,a,b,l,e, ,m,i,s,s,i,n,g)}]_) on id 1 that does not exist.
2021-04-24 18:46:18.062541 -> ERROR: Address(host='192.168.1.7', port=34856) tried to access file (_[{(V,a,r,i,a,b,l,e, ,m,i,s,s,i,n,g)}]_) on id 1 that does not exist.
2021-04-24 18:46:20.103101 -> ERROR: Address(host='192.168.1.7', port=35128) tried to access file (_[{(V,a,r,i,a,b,l,e, ,m,i,s,s,i,n,g)}]_) on id 1 that does not exist.
2021-04-26 14:51:30.981645 -> Warning: Address(host='192.168.1.99', port=41106) created new sensor.
SENSOR: name='string' value='string'
2021-04-27 11:03:50.711031 -> Warning: Address(host='192.168.1.99', port=38418) created new sensor.
SENSOR: name='string' value='string'
2021-04-27 11:04:00.123540 -> Warning: Address(host='192.168.1.99', port=38426) created new sensor.
SENSOR: name='test' value='012'
2021-04-27 11:04:13.492698 -> ERROR: Sensor data download from 1 failed.
ERROR: 1 is not in list
2021-04-27 11:04:56.073021 -> ERROR: Sensor data download from 1 failed.
ERROR: 1 is not in list
2021-04-27 19:13:46.323037 -> Warning: Address(host='192.168.1.99', port=44312) created new sensor.
SENSOR: name='string' value='string'
2021-04-27 19:13:53.203502 -> Warning: Address(host='192.168.1.99', port=44322) created new sensor.
SENSOR: name='test' value='0'
2021-05-02 20:06:54.398494 -> Warning: Address(host='192.168.1.99', port=52808) created new sensor.
SENSOR: name='test' value='0'
2021-05-02 20:38:09.342482 -> Warning: Address(host='192.168.1.99', port=53404) created new sensor.
SENSOR: name='[translate]-tempeature' value='16'
2021-05-02 20:38:31.096100 -> Warning: Address(host='192.168.1.99', port=53422) created new sensor.
SENSOR: name='tempeature' value='16'
2021-05-04 16:11:47.026867 -> Warning: 192.168.1.231 disconnected/is not available

@ -7,6 +7,9 @@ import engine
import requests import requests
import uuid import uuid
import subprocess import subprocess
import socket
import shutil
from pathlib import Path
from fastapi import FastAPI, Request, File, UploadFile from fastapi import FastAPI, Request, File, UploadFile
from fastapi.middleware.cors import CORSMiddleware from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import FileResponse from fastapi.responses import FileResponse
@ -24,8 +27,6 @@ devs = {
"Samuel Šubika": { "Samuel Šubika": {
"git": "https://github.com/JustSteel", "mail": "SteelSamko2000@gmail.com"} "git": "https://github.com/JustSteel", "mail": "SteelSamko2000@gmail.com"}
} }
check = engine.Scan() check = engine.Scan()
check.check_to_go() check.check_to_go()
if check.state_list["error"]: if check.state_list["error"]:
@ -39,11 +40,26 @@ with open("settings.json", "r", encoding='utf-8') as f: # loading settings
with open("filesystem.json", "r", encoding='utf-8') as f: # loading filesystem with open("filesystem.json", "r", encoding='utf-8') as f: # loading filesystem
filesystem = json.load(f) filesystem = json.load(f)
IP = settings["IP"]
ID = settings["ID"]
location = settings["location"]
time_to_save = settings["time_to_save"]
if settings["clear_cache_on_startup"]:
shutil.rmtree("cache")
os.mkdir("cache")
def get_my_ip():
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(("8.8.8.8", 80))
ip = s.getsockname()[0]
s.close()
return ip
IP = get_my_ip()
ID = filesystem["ID"]
location = filesystem["location"]
time_to_save = settings["time_to_save"]
settings["location"]
settings["ID"]
app = FastAPI() # init of FastAPI app = FastAPI() # init of FastAPI
origins = ["*", ] origins = ["*", ]
@ -68,7 +84,7 @@ heartbeat_table = settings["heartbeat_table"]
sensors = {} sensors = {}
messages = [] # {user: "", timestamp: time.Time(), message: ""} messages = [] # {user: "", timestamp: time.Time(), message: ""}
if ID not in heartbeat_table["ID"]:
heartbeat_table["ID"].append(ID) heartbeat_table["ID"].append(ID)
heartbeat_table["IP"].append(IP) heartbeat_table["IP"].append(IP)
heartbeat_table["location"].append(location) heartbeat_table["location"].append(location)
@ -118,17 +134,19 @@ def heartbeat(s_table: ServerTable, request: Request):
log.debug(f"Updated my heartbeat from {s_table.last_heartbeat[position]} to {time_to_heartbeat}") log.debug(f"Updated my heartbeat from {s_table.last_heartbeat[position]} to {time_to_heartbeat}")
heartbeat_table["last_heartbeat"][heartbeat_table["ID"].index(ID)] = time_to_heartbeat heartbeat_table["last_heartbeat"][heartbeat_table["ID"].index(ID)] = time_to_heartbeat
else: else:
heartbeat_table["ID"].append(s_table.ID[position]) log.message(f"Heartbeat from new server:\n ID: {server_id} IP: {request.client}")
heartbeat_table["ID"].append(int(s_table.ID[position]))
heartbeat_table["IP"].append(s_table.IP[position]) heartbeat_table["IP"].append(s_table.IP[position])
heartbeat_table["location"].append(s_table.location[position]) heartbeat_table["location"].append(s_table.location[position])
heartbeat_table["file_system"].append(s_table.file_system[position]) heartbeat_table["file_system"].append(s_table.file_system[position])
heartbeat_table["last_heartbeat"].append(s_table.last_heartbeat[position]) heartbeat_table["last_heartbeat"].append(int(s_table.last_heartbeat[position]))
log.debug(f"Created {server_id}`s heartbeat: {s_table.last_heartbeat[position]}")
except Exception as error: except Exception as error:
log.error(f"heartbeat > {error}") log.error(f"heartbeat > {error}")
if heartbeat_table["ID"][heartbeat_table["IP"].index(request.client.host)] in offline: if heartbeat_table["ID"][heartbeat_table["IP"].index(request.client.host)] in offline:
offline.remove(heartbeat_table["ID"][heartbeat_table["IP"].index(request.client.host)]) offline.remove(heartbeat_table["ID"][heartbeat_table["IP"].index(request.client.host)])
log.message(f"{request.client.host} gone online") log.warning(f"{request.client.host} gone online")
return heartbeat_table, {"ID": ID, "file_system": filesystem, "location": location} return heartbeat_table, {"ID": ID, "file_system": filesystem, "location": location}
@ -136,13 +154,13 @@ def heartbeat(s_table: ServerTable, request: Request):
@app.get("/{IDx}/sensors") @app.get("/{IDx}/sensors")
def get_sensors(IDx: int, request: Request): def get_sensors(IDx: int, request: Request):
global sensors global sensors
log.message(f"sensor data sent to {request.client.host}:{request.client.port}")
log.debug(f"sensor data: {sensors}")
if IDx == ID: if IDx == ID:
log.debug(f"Sensor data sent to {request.client.host} :\n {sensors}")
return sensors return sensors
else: else:
try: try:
r = requests.get(f"""http://{heartbeat_table["IP"][heartbeat_table["ID"].index(IDx)]}:8000/{IDx}/sensors""") r = requests.get(f"""http://{heartbeat_table["IP"][heartbeat_table["ID"].index(IDx)]}:8000/{IDx}/sensors""")
log.debug(f"Sensor data from {IDx} sent to {request.client.host} :\n {r.json()}")
return r.json() return r.json()
except Exception as error: except Exception as error:
log.error(f"Sensor data download from {IDx} failed.\n ERROR: {error}") log.error(f"Sensor data download from {IDx} failed.\n ERROR: {error}")
@ -157,9 +175,10 @@ def get_file(IDx: int, file: str, request: Request):
if os.path.isfile(f"files/{file}"): if os.path.isfile(f"files/{file}"):
return FileResponse(f"files/{file}") return FileResponse(f"files/{file}")
else: else:
return f"File {file} does not exist." log.warning(f"{request.client} tried to access file ({file}) that does not exist on this server.")
return f"ERROR: File {file} does not exist."
if IDx not in heartbeat_table["ID"]: if IDx not in heartbeat_table["ID"]:
log.error(f"{request.client} tried to access id ({IDx}) that does not exist.") log.warning(f"{request.client} tried to access id ({IDx}) that does not exist.")
return f"ERROR: {IDx} does not exist." return f"ERROR: {IDx} does not exist."
else: else:
if os.path.isdir(f"cache/{IDx}"): if os.path.isdir(f"cache/{IDx}"):
@ -174,17 +193,18 @@ def get_file(IDx: int, file: str, request: Request):
else: else:
log.debug(f"returning cached file cache/{IDx}{file}") log.debug(f"returning cached file cache/{IDx}{file}")
return FileResponse(f"cache/{IDx}/{file}") return FileResponse(f"cache/{IDx}/{file}")
elif sum(file.stat().st_size for file in Path("cache").rglob('*'))/1024**2 > settings["cache_size_mb"]:
shutil.rmtree("cache")
os.mkdir("cache")
log.message(f"""Clearing cache, because of limit of {settings["cache_size_mb"]}MB""")
os.mkdir(f"cache/{IDx}")
else: else:
os.mkdir(f"cache/{IDx}") os.mkdir(f"cache/{IDx}")
r = requests.get(f"http://{server_ip}:8000/files/{IDx}/{file}") r = requests.get(f"http://{server_ip}:8000/files/{IDx}/{file}")
if "does not exist" in r.text: if "does not exist" in r.text:
log.error(f"{request.client} tried to access file ({file}) on id {IDx} that does not exist.") log.warning(f"{request.client} tried to access file ({file}) on id {IDx} that does not exist.")
return f"ERROR: {file} does not exist." return f"ERROR: {file} does not exist."
log.message(f"Downloaded {file} from {server_ip}") log.message(f"Downloaded {file} from {server_ip}")
if ".txt" in file:
with open(f"cache/{IDx}/{file}", "wb") as save:
save.write(bytes(r.content))
else:
with open(f"cache/{IDx}/{file}", "wb") as save: with open(f"cache/{IDx}/{file}", "wb") as save:
save.write(bytes(r.content)) save.write(bytes(r.content))
return FileResponse(f"cache/{IDx}/{file}") return FileResponse(f"cache/{IDx}/{file}")
@ -195,6 +215,10 @@ def update_sensors(data: Sensor, request: Request, IDx: int):
global sensors global sensors
if IDx == ID: if IDx == ID:
if data.name in sensors: if data.name in sensors:
if not data.value:
log.message(f"{request.client.host} removed sensor {data.name}")
del sensors[data.name]
else:
log.message(f"{request.client.host} updated sensor {data.name} with value {data.value}") log.message(f"{request.client.host} updated sensor {data.name} with value {data.value}")
sensors[data.name] = data.value sensors[data.name] = data.value
else: else:
@ -228,20 +252,20 @@ def get_devices_list():
@app.get("/admin/get/{command}") @app.get("/admin/get/{command}")
def admin_get(command: str): def admin_get(command: str, request: Request):
log.message(f"{request.client} used admin command.")
if command == "get_updates": if command == "get_updates":
return [update.get_version(), update.get_updates()] return [update.get_version(), update.get_updates()]
if "update-" in command: if "update-" in command:
state = [] state = []
version = command.split("-")[1] version = command.split("-")[1]
return "success"
for rpi in heartbeat_table["IP"]: for rpi in heartbeat_table["IP"]:
if rpi != IP: if rpi != IP:
r = requests.get(f"""http://{rpi}:8000/admin/get/update_one-{version}""") r = requests.get(f"""http://{rpi}:8000/admin/get/update_one-{version}""")
if r.text.strip('"').split("\\n")[0] == "SUCCESS": if r.text.strip('"').split("\\n")[0] == "SUCCESS":
log.message(f"{rpi} was updated to {version}") log.message(f"{rpi} was updated to {version}")
else: else:
log.warning(f"""{rpi} failed to update. Manual update may be needed for proper working of network. log.error(f"""{rpi} failed to update. Manual update may be needed for proper working of network.
Response from server: {r.text}""") Response from server: {r.text}""")
state.append({rpi: r.text.strip('"').split("\\n")}) state.append({rpi: r.text.strip('"').split("\\n")})
subprocess.check_output(f"""python3 system.py update -version {version}""") subprocess.check_output(f"""python3 system.py update -version {version}""")
@ -249,9 +273,8 @@ def admin_get(command: str):
state.append({IP: "updated"}) state.append({IP: "updated"})
return state return state
if "update_one-" in command: if "update_one-" in command:
return "success"
state = subprocess.check_output(["python3", "system.py", "update", "-version", f"""{command.split("-")[1]}"""]) state = subprocess.check_output(["python3", "system.py", "update", "-version", f"""{command.split("-")[1]}"""])
log.warning(state.decode("utf-8")) log.message(state.decode("utf-8"))
return state.decode("utf-8") return state.decode("utf-8")
if command == "heartbeat_table": if command == "heartbeat_table":
return heartbeat_table return heartbeat_table
@ -262,7 +285,6 @@ def admin_get(command: str):
@app.post("/admin/{id_server}/upload_file") @app.post("/admin/{id_server}/upload_file")
async def create_upload_file(id_server: int, uploaded_file: UploadFile = File(...), patch: str = ""): async def create_upload_file(id_server: int, uploaded_file: UploadFile = File(...), patch: str = ""):
file_location = f"{patch}{uploaded_file.filename}" file_location = f"{patch}{uploaded_file.filename}"
print(f"file location: {file_location}")
if id_server == ID: if id_server == ID:
with open(file_location, "wb+") as file_object: with open(file_location, "wb+") as file_object:
file_object.write(uploaded_file.file.read()) file_object.write(uploaded_file.file.read())
@ -316,7 +338,6 @@ def send_heartbeat(ip, id):
global heartbeat_table global heartbeat_table
log.message(f"""sending heartbeat to {ip}({"offline" if id in offline else "online"})""") log.message(f"""sending heartbeat to {ip}({"offline" if id in offline else "online"})""")
cache_request = requests.post(f"http://{ip}:8000/heartbeat", data=json.dumps(heartbeat_table)) cache_request = requests.post(f"http://{ip}:8000/heartbeat", data=json.dumps(heartbeat_table))
print(cache_request.text)
heartbeat_table = dict(cache_request.json()[0]) heartbeat_table = dict(cache_request.json()[0])
log.debug(json.dumps(cache_request.json(), indent=4)) log.debug(json.dumps(cache_request.json(), indent=4))
@ -326,7 +347,7 @@ def mainloop():
while True: while True:
for device_number, device_ID in enumerate(heartbeat_table["ID"]): for device_number, device_ID in enumerate(heartbeat_table["ID"]):
if device_ID != ID: if device_ID != ID:
if heartbeat_table["last_heartbeat"][device_number] < 0: if int(heartbeat_table["last_heartbeat"][device_number]) < 0:
try: try:
send_heartbeat(heartbeat_table["IP"][device_number], heartbeat_table["ID"][device_number]) send_heartbeat(heartbeat_table["IP"][device_number], heartbeat_table["ID"][device_number])
except requests.exceptions.ConnectionError: except requests.exceptions.ConnectionError:
@ -350,7 +371,7 @@ def mainloop():
try: try:
log.debug( log.debug(
f"""{device_ID} : time to heartbeat : {heartbeat_table["last_heartbeat"][device_number]}""") f"""{device_ID} : time to heartbeat : {heartbeat_table["last_heartbeat"][device_number]}""")
heartbeat_table["last_heartbeat"][device_number] -= 1 heartbeat_table["last_heartbeat"][device_number] = int(heartbeat_table["last_heartbeat"][device_number]) - 1
except IndexError: except IndexError:
pass pass
if time.time() - time_to_save > save_time and settings["save_table"]: if time.time() - time_to_save > save_time and settings["save_table"]:
@ -363,12 +384,10 @@ def mainloop():
time.sleep(1) time.sleep(1)
print(f"""Starting WikiSpot V{update.get_version()["version"]}""") print(f"""Starting WikiSpot V{update.get_version()["version"]} on http://{IP}:8000""")
print("GitHub: https://github.com/Tucan444/Mabasej_Team") print("GitHub: https://github.com/Tucan444/Mabasej_Team")
print("Developers of this project: ") print("Developers of this project: ")
for dev in devs: for dev in devs:
print(f"""{dev}, GitHub: {devs[dev]["git"]}, mail: {devs[dev]["mail"]}""") print(f"""{dev}, GitHub: {devs[dev]["git"]}, mail: {devs[dev]["mail"]}""")
thread_1 = threading.Thread(target=mainloop, daemon=True) thread_1 = threading.Thread(target=mainloop, daemon=True)
thread_1.start() thread_1.start()
# Todo settings for easy adding/editing files/id/text

File diff suppressed because it is too large Load Diff

@ -0,0 +1,46 @@
#! /usr/bin/python3
from picamera.array import PiRGBArray
from picamera import PiCamera
import time
import cv2
import imutils
import numpy as np
import requests
protopath = "MobileNetSSD_deploy.prototxt"
modelpath = "MobileNetSSD_deploy.caffemodel"
detector = cv2.dnn.readNetFromCaffe(prototxt=protopath, caffeModel=modelpath)
person_counter = 0
CLASSES = ["background", "aeroplane", "bicycle", "bird", "boat",
"bottle", "bus", "car", "cat", "chair", "cow", "diningtable",
"dog", "horse", "motorbike", "person", "pottedplant", "sheep",
"sofa", "train", "tvmonitor"]
# initialize the camera and grab a reference to the raw camera capture
camera = PiCamera()
rawCapture = PiRGBArray(camera)
# allow the camera to warmup
time.sleep(0.1)
# grab an image from the camera
while True:
camera.capture(rawCapture, format="bgr")
image = rawCapture.array
image = imutils.resize(image, width=1024, height=1024)
(H, W) = image.shape[:2]
blob = cv2.dnn.blobFromImage(image, 0.007843, (W, H), 127.5)
detector.setInput(blob)
person_detections = detector.forward()
for i in np.arange(0, person_detections.shape[2]):
confidence = person_detections[0, 0, i, 2]
if confidence > 0.2:
idx = int(person_detections[0, 0, i, 1])
if CLASSES[idx] == "person":
person_counter += 1
r = requests.post("http://127.0.0.1:8000/update_sensor", json={"name": "pocet ludi", "value": str(person_counter)})
time.sleep(60)

@ -0,0 +1,15 @@
[Unit]
Description=WikiSpot official computer vision plugin
After=wikispot.service
StartLimitIntervalSec=4
[Service]
Type=simple
Restart=always
RestartSec=10
User=root
WorkingDirectory=/root/test_directory/plugins/computer_vision
ExecStart=/root/test_directory/plugins/computer_vision
[Install]
WantedBy=multi-user.target

Binary file not shown.

@ -1,26 +1,25 @@
{ {
"ID": 0,
"IP": "192.168.1.99",
"location": "49.14178021389778,18.353783098441415",
"time_to_heartbeat": 20, "time_to_heartbeat": 20,
"time_to_heartbeat_offline": 25, "time_to_heartbeat_offline": 25,
"save_table": false, "save_table": true,
"time_to_save": 60, "time_to_save": 60,
"max_mess": 20, "max_mess": 20,
"cache_size_mb": 1000,
"clear_cache_on_startup": false,
"log": { "log": {
"save_error": true, "save_error": true,
"print_error": false, "print_error": true,
"save_warning": true, "save_warning": true,
"print_warning": false, "print_warning": true,
"save_message": false, "save_message": false,
"print_message": false, "print_message": true,
"enable_debug": false "enable_debug": false
}, },
"heartbeat_table": { "heartbeat_table": {
"ID": [1], "ID": [],
"IP": ["10.61.42.92"], "IP": [],
"location": [""], "location": [],
"file_system": [""], "file_system": [],
"last_heartbeat": [5] "last_heartbeat": []
} }
} }

@ -1,3 +1,4 @@
#! /usr/bin/python3
import sys import sys
import os import os
import json import json

@ -1,8 +0,0 @@
meno = input("zadajte meno: ")
priezvisko = input("zadajte priezvisko: ")
print(f"Ahoj {meno} {priezvisko} vitaj v programe")
print("-"*24)
print("Ahoj " + meno + " " + priezvisko + " vitaj v programe")
print("-"*24)
print("Ahoj {} {} vitaj v programe".format(meno, priezvisko))

@ -1,28 +0,0 @@
{
"ID": 0,
"location": "49.14178021389778,18.353783098441415",
"description": {
"title": "legionrpi",
"description_s": "kr\u00e1tky popis, ktor\u00fd bude zobrazen\u00fd iba v n\u00e1hladovom okne",
"description_l": "dlh\u0161\u00ed popis zariadenia, ktor\u00fd bude zobrazen\u00fd po otvoren\u00ed",
"photo_s": "test.jpg",
"photo_b": "test.png"
},
"files": [
{
"name": "test",
"format": ".jpg",
"description": "toto je jpg test file"
},
{
"name": "test2",
"format": ".txt",
"description": "toto je txt test file"
},
{
"name": "Wikispot",
"format": "docx",
"description": "Test"
}
]
}

@ -1,83 +0,0 @@
import socket
import multiprocessing
import subprocess
import os
def pinger(job_q, results_q):
"""
Do Ping
:param job_q:
:param results_q:
:return:
"""
DEVNULL = open(os.devnull, 'w')
while True:
ip = job_q.get()
if ip is None:
break
results_q.put(ip)
def get_my_ip():
"""
Find my IP address
:return:
"""
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(("8.8.8.8", 80))
ip = s.getsockname()[0]
s.close()
return ip
def map_network(pool_size=255):
"""
Maps the network
:param pool_size: amount of parallel ping processes
:return: list of valid ip addresses
"""
ip_list = list()
my_ip = get_my_ip()
# get my IP and compose a base like 192.168.1.xxx
ip_parts = get_my_ip().split('.')
base_ip = ip_parts[0] + '.' + ip_parts[1] + '.' + ip_parts[2] + '.'
# prepare the jobs queue
jobs = multiprocessing.Queue()
results = multiprocessing.Queue()
pool = [multiprocessing.Process(target=pinger, args=(jobs, results)) for i in range(pool_size)]
for p in pool:
p.start()
# cue hte ping processes
for i in range(1, 255):
jobs.put(base_ip + '{0}'.format(i))
for p in pool:
jobs.put(None)
for p in pool:
p.join()
# collect he results
while not results.empty():
ip = results.get()
if ip != my_ip:
ip_list.append(ip)
return ip_list
if __name__ == '__main__':
print('Mapping...')
lst = map_network()
print(lst)

@ -1,331 +0,0 @@
import tkinter
from tkinter.filedialog import askopenfilename
import requests
import json
import tkinter.messagebox
import os
window = tkinter.Tk()
window.title("WikiSpot Editor")
sellected = None
sellected_index = None
filename = None
textn1 = None
textn2 = None
textn3 = None
ip = "127.0.0.1"
data = None
rpi_active = []
# commands
def save_changes():
data[sellected_index]["description"]["title"] = text1.get()
data[sellected_index]["location"] = text2.get()
data[sellected_index]["description"]["description_s"]
data[sellected_index]["description"]["description_l"]
def update_server_refresh(text_window, description):
text_window.configure(state="normal")
text_window.delete('1.0', "end")
text_window.insert("end", description)
text_window.configure(state="disable")
def update_server_func(version, servers_all=True):
if servers_all:
if tkinter.messagebox.askyesno(title="Warning", message=f"WikiSpot Network will update to\n V{version}"):
r = requests.get(f"http://{ip}:8000/admin/get/update-{version}")
tkinter.messagebox.showinfo(title="Done", message=r.text)
else:
if tkinter.messagebox.askyesno(title="Warning", message=f"WikiSpot Server will update to\n V{version}"):
r = requests.get(f"http://{ip}:8000/admin/get/update-one-{version}")
tkinter.messagebox.showinfo(title="Done", message=r.text)
def update_server():
r = requests.get(f"http://{ip}:8000/admin/get/get_updates")
versions = json.loads(r.text)
versions_server = list(versions[1].keys())
window_update_server = tkinter.Toplevel()
window_update_server.title("server update")
variable = tkinter.StringVar(window_update_server)
variable.set(versions_server[-1]) # default value
version_menu = tkinter.OptionMenu(window_update_server, variable, *versions_server)
label1 = tkinter.Label(window_update_server, text="WikiSpot verison: ")
label2 = tkinter.Label(window_update_server, text=versions[0]["version"])
label3 = tkinter.Label(window_update_server, text="Versions")
label4 = tkinter.Label(window_update_server, text="Release news")
b1 = tkinter.Button(window_update_server, text="Update all", command=lambda: update_server_func(variable.get()))
b2 = tkinter.Button(window_update_server, text="Update one", command=lambda: update_server_func(variable.get(), servers_all=False))
b3 = tkinter.Button(window_update_server, text="Exit", command=lambda: window_update_server.destroy())
text = tkinter.Text(window_update_server, width=50, height=10)
text.insert("end", versions[1][variable.get()]["change_list"])
variable.trace("w", lambda *args: update_server_refresh(text, versions[1][variable.get()]["change_list"]))
label1.grid(row=0, column=0)
label2.grid(row=0, column=1)
label3.grid(row=1, column=0)
label4.grid(row=2, column=0)
version_menu.grid(row=1, column=1)
text.grid(row=2, column=1)
b1.grid(row=3, column=0)
b2.grid(row=3, column=1)
b3.grid(row=3, column=2)
window_update_server.mainloop()
def upload_new_file(name, window, file_format, description, *patch: str):
global data
if " " in name:
tkinter.messagebox.showerror(title="Error", message="File name needs to be without spaces.\nApp on mobile will "
"change `_` to space.")
else:
data[sellected_index]["files"].append({
"name": name,
"format": file_format,
"description": description.get("1.0", "end").replace("\n", "")
})
print("saving")
with open("./test.json", "w", encoding='utf-8') as fp:
json.dump(dict(data[sellected_index]), fp, indent=2)
with open("test.json", "rb") as fp:
requests.post(f"http://{ip}:8000/admin/{sellected}/upload_file", files={"uploaded_file": fp})
os.remove("test.json")
if patch:
with open(patch[0], "rb") as fp:
requests.post(f"http://{ip}:8000/admin/{sellected}/upload_file", files={"uploaded_file": fp, "patch": "files/"}, params={"patch": "files/"})
window.destroy()
def new_file(*itnpu):
global filename, sellected
window_new = tkinter.Toplevel()
window_new.title("New File")
if sellected not in rpi_active:
tkinter.messagebox.showerror(title="Error", message="Server is not selected!")
window_new.destroy()
else:
filename = askopenfilename()
while not filename:
if not tkinter.messagebox.askretrycancel(title="Warning", message="File not selected."):
window_new.destroy()
break
filename = askopenfilename()
if filename:
label1 = tkinter.Label(window_new, text="FileName")
label2 = tkinter.Label(window_new, text="FileExtension")
label3 = tkinter.Label(window_new, text="Description")
label4 = tkinter.Label(window_new, text=str(filename.split("/")[-1].split(".")[0]))
label5 = tkinter.Label(window_new, text=str(filename.split("/")[-1].split(".")[1]))
in3 = tkinter.Text(window_new, height=8, width=40)
b1 = tkinter.Button(window_new, text="UPLOAD", command=lambda: upload_new_file(
str(filename.split("/")[-1].split(".")[0]), window_new,
str(filename.split("/")[-1].split(".")[1]), in3, filename), width=40, height=2)
b2 = tkinter.Button(window_new, text="EXIT", command=window_new.destroy, height=2)
label1.grid(row=0, column=0)
label2.grid(row=1, column=0)
label3.grid(row=2, column=0)
label4.grid(row=0, column=1)
label5.grid(row=1, column=1)
in3.grid(row=2, column=1)
b1.grid(row=3, column=1)
b2.grid(row=3, column=0)
window_new.mainloop()
def edit_file(file_name):
window_edit = tkinter.Toplevel()
window_edit.title("edit_file")
try:
for file in data[sellected_index]["files"]:
if file["name"] == file_name:
sellected_file_index = data[sellected_index]["files"].index(file)
break
else:
sellected_file_index = None
label1 = tkinter.Label(window_edit, text="Name\n(you can change name and\nformat only by uploading\nnew file)")
label2 = tkinter.Label(window_edit, text="Format")
label3 = tkinter.Label(window_edit, text="Description")
label4 = tkinter.Label(window_edit, text=data[sellected_index]["files"][sellected_file_index]["name"])
label5 = tkinter.Label(window_edit, text=data[sellected_index]["files"][sellected_file_index]["format"])
text = tkinter.Text(window_edit, height=8, width=40)
text.insert("end", data[sellected_index]["files"][sellected_file_index]["description"])
button1 = tkinter.Button(window_edit, text="Exit", command=lambda: window_edit.destroy())
button2 = tkinter.Button(window_edit, text="Save", command=lambda: upload_new_file(
data[sellected_index]["files"][sellected_file_index]["name"], window_edit,
data[sellected_index]["files"][sellected_file_index]["format"], text))
button3 = tkinter.Button(window_edit, text="Remove", command=lambda: upload_new_file(
data[sellected_index]["files"][sellected_file_index]["name"], window_edit, "_REMOVE_", text))
label1.grid(row=0, column=0)
label2.grid(row=1, column=0)
label3.grid(row=2, column=0)
label4.grid(row=0, column=1)
label5.grid(row=1, column=1)
text.grid(row=2, column=1)
button1.grid(row=3, column=0)
button2.grid(row=3, column=1)
button3.grid(row=3, column=2)
window_edit.mainloop()
except TypeError:
tkinter.messagebox.showerror(title="Error", message="No file sellected!\n"
"Select server and then file you want to edit.")
window_edit.destroy()
def update_inputs(self):
global sellected, sellected_index, data
try:
if int(list_rpi.selection_get()) in rpi_active:
sellected = int(list_rpi.selection_get())
for rpi in data:
if rpi["ID"] == sellected:
sellected_index = data.index(rpi)
text1.set(data[sellected_index]["ID"])
text2.set(data[sellected_index]["location"])
list2.clipboard_clear()
list2.delete(0, "end")
for file in data[sellected_index]["files"]:
list2.insert("end", file["name"])
except ValueError or tkinter.TclError:
print(f"Exception: list_rpi sellection = {list_rpi.selection_get()}")
def update_listbox():
global data, rpi_active
r = requests.get(f"http://{ip}:8000/devices_list")
data = json.loads(r.text)
del data[0]
print(data)
list_rpi.delete(0, "end")
rpi_active.clear()
for rpi in data:
list_rpi.insert("end", rpi["ID"])
rpi_active.append(rpi["ID"])
# for rpi in zoznam:
# list_rpi.insert("end", rpi)
def clear_listbox():
list_rpi.delete(0, "end")
def cmd1():
print(list_rpi.selection_get())
# menu
menu = tkinter.Menu(window)
menu.master.config(menu=menu)
# file
menu_submenu1 = tkinter.Menu(menu, tearoff=0)
menu.add_cascade(label="File", menu=menu_submenu1)
menu_submenu1.add_command(label="refresh", command=update_listbox)
menu_submenu1.add_separator()
menu_submenu1.add_command(label="exit", command=exit)
# about
menu_submenu2 = tkinter.Menu(menu, tearoff=0)
menu.add_cascade(label="About", menu=menu_submenu2)
menu_submenu2.add_command(label="Check server updates", command=update_server)
menu_submenu2.add_command(label="Check app updates", command=update_listbox)
menu_submenu2.add_separator()
menu_submenu2.add_command(label="About WikiSpot", command=exit)
menu_submenu2.add_command(label="About Editor", command=exit)
# labels
l1 = tkinter.Label(window, text='label1')
l1.grid(row=0, column=0)
l2 = tkinter.Label(window, text='label2')
l2.grid(row=0, column=2)
l3 = tkinter.Label(window, text='label3')
l3.grid(row=1, column=0)
l4 = tkinter.Label(window, text='label4')
l4.grid(row=1, column=2)
l5 = tkinter.Label(window, text='Servers:')
l5.grid(row=2, column=0)
l6 = tkinter.Label(window, text='Files: ')
l6.grid(row=2, column=5)
# entries
text1 = tkinter.StringVar()
en1 = tkinter.Entry(window, textvariable=text1)
en1.grid(row=0, column=1)
text2 = tkinter.StringVar()
en2 = tkinter.Entry(window, textvariable=text2)
en2.grid(row=0, column=3)
text3 = tkinter.StringVar()
en3 = tkinter.Entry(window, textvariable=text3)
en3.grid(row=1, column=1)
text4 = tkinter.StringVar()
en4 = tkinter.Entry(window, textvariable=text4)
en4.grid(row=1, column=3)
# listbox
list_rpi = tkinter.Listbox(window, height=6, width=35)
list_rpi.grid(row=3, column=0, rowspan=6, columnspan=2)
list_rpi.bind("<<ListboxSelect>>", update_inputs)
list2 = tkinter.Listbox(window, height=6, width=35)
list2.grid(row=3, column=5, rowspan=6, columnspan=2)
# list_rpi.bind("<<ListboxSelect>>", update_inputs)
# scrollbar
sb1 = tkinter.Scrollbar(window)
sb1.grid(row=2, column=2, rowspan=6)
list_rpi.configure(yscrollcommand=sb1.set)
sb1.configure(command=list_rpi.yview)
sb2 = tkinter.Scrollbar(window)
sb2.grid(row=2, column=7, rowspan=6)
list2.configure(yscrollcommand=sb2.set)
sb2.configure(command=list2.yview)
# buttons
btn1 = tkinter.Button(window, text="exit", width=12, command=update_listbox)
btn1.grid(row=6, column=3)
btn2 = tkinter.Button(window, text="add server", width=12, command=clear_listbox)
btn2.grid(row=3, column=3)
btn3 = tkinter.Button(window, text="place", width=12, command=new_file)
btn3.grid(row=4, column=3)
btn4 = tkinter.Button(window, text="place", width=12, command=lambda: edit_file(list2.selection_get()))
btn4.grid(row=5, column=3)
btn5 = tkinter.Button(window, text="save", width=12, command=update_listbox)
btn5.grid(row=6, column=4)
btn5 = tkinter.Button(window, text="new file", width=12, command=new_file)
btn5.grid(row=3, column=4)
btn5 = tkinter.Button(window, text="edit file", width=12, command=new_file)
btn5.grid(row=4, column=4)
btn5 = tkinter.Button(window, text="place", width=12, command=lambda: window.destroy())
btn5.grid(row=5, column=4)
update_listbox()
window.mainloop()

@ -1,4 +1,4 @@
{ {
"version": "0.9", "version": "1.0",
"id": 6 "id": 7
} }