diff --git a/Makefile b/Makefile index 86a9edf..7b5c9d8 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,8 @@ -publish: - pip install twine - python setup.py sdist - twine upload dist/* +clean: + rm -rf dist cosmicpi.egg-info build + +publish: clean + python setup.py sdist upload ci-publish: echo '[pypi]' > ~/.pypirc diff --git a/README.md b/README.md index 047c58d..bd7c265 100644 --- a/README.md +++ b/README.md @@ -2,73 +2,31 @@ [![Build Status](https://travis-ci.org/CosmicPi/cosmicpi-rpi_V1.5.svg?branch=rest)](https://travis-ci.org/CosmicPi/cosmicpi-rpi_V1.5) -This software runs on the raspberry pi, which is integral to the CosmicPi V1.5. +This software runs on the Raspberry Pi, which is integral to the CosmicPi V1.5. The central point is a SQLite database into which data is stored, as well as read from. More instructions will follow when the software has reached the state of the V2 mock-up software. -#### If you encounter any problems, please follow these steps: -1. Consult the manual, if available to you -2. Consult the [CosmicPi blog](http://cosmicpi.org/posts) (maybe the issue is very common and we have posted a solution for you) -3. Submit an issue here on github via the *Issues* tab, make sure to include the following: - * What you are expecting to get from the detector/software - * What you are currently getting from the detector/software - * The version of the software that you are running - * Any log output available to you (the more the better) - * Any and all clues that you have on what might be going wrong - -## Current features -* All that is checked off in the next section -* *Note*: The parser will only store data if the detector is fully working, e.g. Sensors are working/enabled and the GPS has a connection / is working. -This behaviour is very much open to discussion. - - -## Needed features to match up with the Version 2 mock-up software -- [x] Read data from the Arduino Due (detector) into the SQLite database -- [x] Display basic information in the WebUI -- [x] Start application on boot -- [x] Start hotspot on boot -- [x] Connect to a different WiFi via the WebUI -- [x] Working install procedure -- [x] SystemD services for all components - - [x] Detector readout - - [x] WebUI - - [x] Hotspot -- [x] Interface for getting the raw data and database dumps -- [x] Authentication for the settings page -- [x] Interface to create custom plots -- [x] Include about page -- [x] Add useful configurations to the config file -- [x] Do a test of the installation on a clean raspbian lite installation -- [ ] Do an as complete as possible test of all components after a fresh installation - - - ## Installation -Clone this repository to the home folder of your CosmicPi (e.g. `/home/pi`). Switch into the repository (e.g. `cd /home/pi/cosmicpi-rpi_V1.5`). -Then run: +For CosmicPi software installation only please use: +``` +pip install cosmicpi +``` -```./install``` +If you have scratch Raspbian image and you want to install software, expand filesystem, configure AP... please use: +``` +curl https://gist.githubusercontent.com/lukicdarkoo/e33e00c6780ad0215d3932b810a10e46/raw | sh +``` -Though I have tested different parts of the installation script, I have not yet tested the whole thing on a completely clean system. -E.g.: The installation may or may not work. -The installation will most likely take some time. Especially on the raspbian lite distribution numpy will need to be compiled first and that takes quite long. -It would be great if you were to give it a try anyways. -In case something fails, please submit an issue with the output you got. Thanks! ## Run -The software is normally controlled via SystemD. -*Optional:* Reboot to automatically start the software as a SystemD service. +The software is normally controlled via SystemD. The following services are available: +- cosmicpi-ui +- cosmicpi-rest +- cosmicpi-mqtt +- cosmicpi-dbcleaner +- cosmicpi-detector -**Start or stop the detector connector:** `sudo systemctl start CosmicPi-detector` or `sudo systemctl stop CosmicPi-detector` - -**Start or stop the WebUI:** `sudo systemctl start CosmicPi-UI` or `sudo systemctl stop CosmicPi-UI` - -**Start or stop the Hotspot:** `sudo systemctl start hostapd` or `sudo systemctl stop hostapd -Note that you should also start and stop the dnsmasq service with the hostapd.` - -**View the log output:** `sudo systemctl status CosmicPi-detector` or `sudo systemctl status CosmicPi-UI` or `sudo systemctl status create_ap` - -From the raspberry pi itself the application is available at: +From the Raspberry Pi itself the application is available at: `http://cosmicpi.local/` or `http://127.0.0.1/` @@ -78,13 +36,3 @@ When used as an access point the application is available at: #### Debugging the software: Stop all mentioned services. After this you should be able to run the software directly via the commandline. - -## Proposed future features -* Enforce read only access to the DB for the UI -* Setup proper logging mechanisms for all parts of the software (maybe with journalD ?) -* Create additional ways to work with the data, focused on the needs of teachers in schools -* Database maintenance: Look at ways to aggregate the data, to avoid bloating of the database -* Do the installation in a proper way, as example with setuptools -* Run flask on an actual webserver, not the built-in development server -* Lock the settings page behind a password protection (create a session in flask, etc.) [DONE] -* Sqlite database on a ram disk, should speed up access times dramatically diff --git a/cosmicpi/rest/wifi.py b/cosmicpi/rest/wifi.py index 4cacd2a..b3e6750 100644 --- a/cosmicpi/rest/wifi.py +++ b/cosmicpi/rest/wifi.py @@ -5,11 +5,8 @@ from .auth import requires_auth import subprocess import re import time +import os from functools import wraps -try: - import thread -except: - import _thread as thread try: import urllib2 except: @@ -64,113 +61,35 @@ class Wifi(Resource): @requires_auth def post(self): ssid = request.form['ssid'] - password = request.form['pass'] + psk = request.form['pass'] - thread.start_new_thread(connect_to_wifi, (ssid, password)) + # Try to connect to a new Wifi + wpa_supplicant_content = """ +country=US +ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev +update_config=1 +network={ + ssid="%s" + psk="%s" + id_str="AP1" +} + """ % (ssid, psk) + with open(WPA_SUPPLICANT_LOCATION, 'w') as file: + file.write(wpa_supplicant_content) + os.system('sudo ifdown wlan0 --force; sudo ifup wlan0; wpa_supplicant -i wlan0 -c %s' % WPA_SUPPLICANT_LOCATION) - msg = 'The CosmicPi will now try to connect to the WiFi "{}". ' \ - "If no internet connection is found or the connection was not " \ - "successful the CosmiPi will recreate the WiFi hotspot. Please " \ - "wait at least two minutes.".format(ssid) + # Get new IP + new_ip = subprocess.check_output( + "ifconfig wlan0 | awk '/inet / {print $2}'", + shell=True + ).decode('utf-8').strip() + + # Return result + if len(new_ip) > 0: + return { + 'message': 'Great! Your are not connected to %s and you can access to ' \ + 'this web panel on http://%s/' % (ssid, new_ip), + } return { - 'message': msg - } - - -def fall_back_to_ap(): - # empty the wpa supplicant to it's default - wpa_supplicant_string = "country=GB\n" # Todo: Check, that this string in front is still correct! - wpa_supplicant_string += "ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev\n" - wpa_supplicant_string += "update_config=1\n" - wpa_supplicant_string += "\nnetwork={\n" - net = (DEFAULT_WIFI_NAME, DEFAULT_WIFI_PASS) - wpa_supplicant_string += '\tssid="{}"\n'.format(net[0]) - # check if we need a password - if str(net[1]) == "": - wpa_supplicant_string += '\tpsk="{}"\n'.format(net[1]) - wpa_supplicant_string += "}\n" - with open(WPA_SUPPLICANT_LOCATION, 'w') as file: - file.write(wpa_supplicant_string) - # configure controler to accept the new configuration - try: - import fcntl - time.sleep(2) - subprocess.call("wpa_cli -i wlan0 reconfigure", shell=True) - time.sleep(2) - except ImportError: - print("This OS is not linux enough to handle a hotspot in this way") - - # restart the hotspot - try: - import fcntl - subprocess.call("systemctl start dnsmasq", - shell=True) # well, here we actually care if the hotspot starts, but oh well... - time.sleep(2) - subprocess.call("ifconfig wlan0 down", shell=True) - time.sleep(2) - subprocess.call("ifconfig wlan0 up", shell=True) - except ImportError: - print("This OS is not linux enough to handle a hotspot in this way") - - -def connect_to_wifi(name, pw): - # build the string for the WPA supplicant - wpa_supplicant_string = "country=GB\n" # Todo: Check, that this string in front is still correct! - wpa_supplicant_string += "ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev\n" - wpa_supplicant_string += "update_config=1\n" - networks = [(name, pw), (DEFAULT_WIFI_NAME, DEFAULT_WIFI_PASS)] - for net in networks: - wpa_supplicant_string += "\nnetwork={\n" - wpa_supplicant_string += '\tssid="{}"\n'.format(net[0]) - # check if we need a password - if not str(net[1]) == "": - wpa_supplicant_string += '\tpsk="{}"\n'.format(net[1]) - wpa_supplicant_string += "}\n" - - # deactivate htospot and turn the WiFi back on - try: - import fcntl - subprocess.call("systemctl stop dnsmasq", shell=True) # we very much don't care if this fails - time.sleep(2) - subprocess.call("ifconfig wlan0 down", shell=True) - time.sleep(2) - subprocess.call("ifconfig wlan0 up", shell=True) - except ImportError: - print("This OS is not linux enough to handle a hotspot in this way") - # write wpa_supplicant string to the file - with open(WPA_SUPPLICANT_LOCATION, 'w') as file: - file.write(wpa_supplicant_string) - # configure controler to accept the new configuration - try: - import fcntl - time.sleep(2) - subprocess.call("wpa_cli -i wlan0 reconfigure", shell=True) - except ImportError: - print("This OS is not linux enough to handle a hotspot in this way") - - # wait for an internet connection (max 2 min) - start_time = time.time() - have_internet = False - while not have_internet and ((start_time + 120) > time.time()): - have_internet = internet_on() - - # if we have no internet, restart the hotspot, otherwise we are done for now - if have_internet: - print("Successfully connected to the internet (yeah)") - # wait a bit before we send the mail - time.sleep(5) - # ToDo: This would be a good point to send a mail or something similar to the user. - # Just to inform them where their cosmicPi is and what's it doing - return - else: - print("No internet connection here, falling back to hotspot!") - fall_back_to_ap() - return - - -def internet_on(): - try: - urllib2.urlopen('http://heise.de', timeout=2) - return True - except urllib2.URLError: - return False + 'message': 'Something went wrong, unable to connect :(', + } \ No newline at end of file diff --git a/setup.py b/setup.py index 49f40b0..28052d6 100644 --- a/setup.py +++ b/setup.py @@ -1,5 +1,7 @@ from setuptools import setup from setuptools.command.install import install +from setuptools.command.develop import develop +from setuptools.command.egg_info import egg_info import os @@ -60,15 +62,29 @@ POSTINSTALL = """ """ -class PrePostInstall(install): +class CustomInstallCommand(install): def run(self): os.system(PREINSTALL) install.run(self) os.system(POSTINSTALL) +class CustomDevelopCommand(develop): + def run(self): + os.system(PREINSTALL) + develop.run(self) + os.system(POSTINSTALL) + + +class CustomEggInfoCommand(egg_info): + def run(self): + os.system(PREINSTALL) + egg_info.run(self) + os.system(POSTINSTALL) + + setup(name='cosmicpi', - version='1.5.4', + version='1.5.6', description='UI for the CosmicPi cosmic ray detector', long_description='This software provides the user interface, temporary storage and connection to the internet storage for the detectors of the CosmicPi project. The Cosmic Pi project aims to build the world\'s largest open source distributed cosmic ray telescope. You too can be a part of the project, by becoming a Cosmic Pixel!', platforms=['noarch'], @@ -92,7 +108,7 @@ setup(name='cosmicpi', 'cosmicpi.storage': ['cosmicpi.sqlite3'], }, data_files=[ - ('/etc/systemd/system/', [ + ('/etc/systemd/system', [ 'data_files/cosmicpi-ui.service', 'data_files/cosmicpi-mqtt.service', 'data_files/cosmicpi-detector.service', @@ -120,6 +136,8 @@ setup(name='cosmicpi', 'bin/cosmicpi-ui', ], cmdclass={ - 'install': PrePostInstall, + 'install': CustomInstallCommand, + 'develop': CustomDevelopCommand, + 'egg_info': CustomEggInfoCommand, }, )