Merge branch 'Development' of https://github.com/Tucan444/Mabasej_Team into Development
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*
|
||||||
|
6
app/WikiSpot/.idea/vcs.xml
Normal file
@ -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>
|
BIN
new new files/files/Jedálny lístok.pdf
Normal file
22
new new files/files/Podrobnosti.txt
Normal file
@ -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
|
BIN
new new files/files/restaurant_in.jpg
Normal file
After Width: | Height: | Size: 315 KiB |
BIN
new new files/files/restaurant_out.jpg
Normal file
After Width: | Height: | Size: 69 KiB |
BIN
new new files/files1/Cenník.pdf
Normal file
17
new new files/files1/Podrobnosti.txt
Normal file
@ -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
|
BIN
new new files/files1/post_out.jpg
Normal file
After Width: | Height: | Size: 304 KiB |
BIN
new new files/files1/posta_in.jpg
Normal file
After Width: | Height: | Size: 72 KiB |
BIN
new new files/files2/Bazény a cenník.pdf
Normal file
23
new new files/files2/Služby a kontakt.txt
Normal file
@ -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
|
BIN
new new files/files2/plavaren_in.jpg
Normal file
After Width: | Height: | Size: 158 KiB |
BIN
new new files/files2/plavaren_out.jpg
Normal file
After Width: | Height: | Size: 474 KiB |
BIN
new new files/files3/Cenník.pdf
Normal file
BIN
new new files/files3/Náhľad.pdf
Normal file
BIN
new new files/files3/muzeum_in.jpg
Normal file
After Width: | Height: | Size: 122 KiB |
BIN
new new files/files3/muzeum_out.jpg
Normal file
After Width: | Height: | Size: 10 KiB |
18
new new files/files4/Podrobnosti.txt
Normal file
@ -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
|
BIN
new new files/files4/Zľavy.pdf
Normal file
BIN
new new files/files4/zeleznicna_stanica_in.jpg
Normal file
After Width: | Height: | Size: 1.1 MiB |
BIN
new new files/files4/zeleznicna_stanica_out.jpg
Normal file
After Width: | Height: | Size: 55 KiB |
24
new new files/filesystem.json
Normal file
@ -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": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
24
new new files/filesystem1.json
Normal file
@ -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": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
24
new new files/filesystem2.json
Normal file
@ -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": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
24
new new files/filesystem3.json
Normal file
@ -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"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
24
new new files/filesystem4.json
Normal file
@ -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
After Width: | Height: | Size: 354 KiB |
BIN
server/files.zip
@ -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
|
|
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"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
203
server/log.txt
@ -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
|
|
101
server/main.py
@ -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,12 +84,12 @@ 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)
|
||||||
heartbeat_table["file_system"].append(filesystem)
|
heartbeat_table["file_system"].append(filesystem)
|
||||||
heartbeat_table["last_heartbeat"].append(time_to_heartbeat)
|
heartbeat_table["last_heartbeat"].append(time_to_heartbeat)
|
||||||
|
|
||||||
|
|
||||||
class ServerTable(BaseModel): # table of content for heartbeat request
|
class ServerTable(BaseModel): # table of content for heartbeat request
|
||||||
@ -111,24 +127,26 @@ def heartbeat(s_table: ServerTable, request: Request):
|
|||||||
s_table.last_heartbeat[position]:
|
s_table.last_heartbeat[position]:
|
||||||
heartbeat_table["last_heartbeat"][heartbeat_table["ID"].index(server_id)] = s_table.last_heartbeat[
|
heartbeat_table["last_heartbeat"][heartbeat_table["ID"].index(server_id)] = s_table.last_heartbeat[
|
||||||
position]
|
position]
|
||||||
log.debug(f"updated {server_id}`s heartbeat to {s_table.last_heartbeat[position]}")
|
log.debug(f"updated {server_id}`s heartbeat to {s_table.last_heartbeat[position]}")
|
||||||
heartbeat_table["file_system"][heartbeat_table["ID"].index(server_id)] = s_table.file_system[
|
heartbeat_table["file_system"][heartbeat_table["ID"].index(server_id)] = s_table.file_system[
|
||||||
position]
|
position]
|
||||||
elif server_id == ID:
|
elif server_id == ID:
|
||||||
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,19 +193,20 @@ 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:
|
||||||
with open(f"cache/{IDx}/{file}", "wb") as save:
|
save.write(bytes(r.content))
|
||||||
save.write(bytes(r.content))
|
|
||||||
else:
|
|
||||||
with open(f"cache/{IDx}/{file}", "wb") as save:
|
|
||||||
save.write(bytes(r.content))
|
|
||||||
return FileResponse(f"cache/{IDx}/{file}")
|
return FileResponse(f"cache/{IDx}/{file}")
|
||||||
|
|
||||||
|
|
||||||
@ -195,8 +215,12 @@ 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:
|
||||||
log.message(f"{request.client.host} updated sensor {data.name} with value {data.value}")
|
if not data.value:
|
||||||
sensors[data.name] = 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}")
|
||||||
|
sensors[data.name] = data.value
|
||||||
else:
|
else:
|
||||||
log.warning(f"{request.client} created new sensor.\n SENSOR: {data}")
|
log.warning(f"{request.client} created new sensor.\n SENSOR: {data}")
|
||||||
sensors[data.name] = data.value
|
sensors[data.name] = data.value
|
||||||
@ -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
|
|
||||||
|
BIN
server/plugins/computer_vision/MobileNetSSD_deploy.caffemodel
Normal file
1912
server/plugins/computer_vision/MobileNetSSD_deploy.prototxt
Normal file
46
server/plugins/computer_vision/com_vision.py
Normal file
@ -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
|
@ -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
|
||||||
}
|
}
|
||||||
|