Merge pull request 'data_read' (#1) from data_read into main
Reviewed-on: #1
This commit is contained in:
		
						commit
						21c9b05182
					
				
							
								
								
									
										5
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| 
						 | 
					@ -158,7 +158,4 @@ cython_debug/
 | 
				
			||||||
#  be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
 | 
					#  be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
 | 
				
			||||||
#  and can be added to the global gitignore or merged into this file.  For a more nuclear
 | 
					#  and can be added to the global gitignore or merged into this file.  For a more nuclear
 | 
				
			||||||
#  option (not recommended) you can uncomment the following to ignore the entire idea folder.
 | 
					#  option (not recommended) you can uncomment the following to ignore the entire idea folder.
 | 
				
			||||||
#.idea/
 | 
					#.idea/
 | 
				
			||||||
 | 
					 | 
				
			||||||
bluewind
 | 
					 | 
				
			||||||
bluewind/*
 | 
					 | 
				
			||||||
							
								
								
									
										23
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										23
									
								
								README.md
									
									
									
									
									
								
							| 
						 | 
					@ -6,10 +6,29 @@ Bluetooth control app for Wahoo Headwind.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Usage
 | 
					## Usage
 | 
				
			||||||
 | 
					
 | 
				
			||||||
To run the flask app:
 | 
					To run the flask app for development and testing:
 | 
				
			||||||
```bash
 | 
					```bash
 | 
				
			||||||
 | 
					git clone https://teapot.octopusx.de/accidentallycompetent/bluewind.git
 | 
				
			||||||
 | 
					cd bluewind
 | 
				
			||||||
 | 
					python3 -m venv .venv
 | 
				
			||||||
 | 
					source .venv/bin/activate
 | 
				
			||||||
 | 
					python3 -m pip install --upgrade pip
 | 
				
			||||||
 | 
					pip3 install -r requirements.txt
 | 
				
			||||||
export FLASK_ADDRESS='<headwind bluetooth address>'
 | 
					export FLASK_ADDRESS='<headwind bluetooth address>'
 | 
				
			||||||
flask --app api run --host=0.0.0.0
 | 
					export FLASK_URL='<address and port to bind'
 | 
				
			||||||
 | 
					python3 main.py
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					To run the flask app in a permanent deployment:
 | 
				
			||||||
 | 
					```bash
 | 
				
			||||||
 | 
					git clone https://teapot.octopusx.de/accidentallycompetent/bluewind.git
 | 
				
			||||||
 | 
					cd bluewind
 | 
				
			||||||
 | 
					python3 -m venv .venv
 | 
				
			||||||
 | 
					source .venv/bin/activate
 | 
				
			||||||
 | 
					python3 -m pip install --upgrade pip
 | 
				
			||||||
 | 
					pip3 install -r requirements.txt
 | 
				
			||||||
 | 
					cp default.env .env # modify your .env file!
 | 
				
			||||||
 | 
					sudo /bin/bash scripts/install.sh # will install and start+enable the systemd service for you
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Support
 | 
					## Support
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										46
									
								
								api.py
									
									
									
									
									
								
							
							
						
						
									
										46
									
								
								api.py
									
									
									
									
									
								
							| 
						 | 
					@ -1,46 +0,0 @@
 | 
				
			||||||
#!/usr/bin/env python3
 | 
					 | 
				
			||||||
from flask import Flask
 | 
					 | 
				
			||||||
from headwind import Headwind as Headwind
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
app = Flask(__name__)
 | 
					 | 
				
			||||||
app.config.from_prefixed_env()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@app.route("/on")
 | 
					 | 
				
			||||||
async def on():
 | 
					 | 
				
			||||||
    fan = Headwind(app, app.config["ADDRESS"])
 | 
					 | 
				
			||||||
    fan_status = await fan.on()
 | 
					 | 
				
			||||||
    if not fan_status:
 | 
					 | 
				
			||||||
        return "<p>Failed to turn headwind on</p>", 503
 | 
					 | 
				
			||||||
    return "<p>Turning headwind on</p>", 200
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@app.route("/sleep")
 | 
					 | 
				
			||||||
async def sleep():
 | 
					 | 
				
			||||||
    fan = Headwind(app, app.config["ADDRESS"])
 | 
					 | 
				
			||||||
    fan_status = await fan.sleep()
 | 
					 | 
				
			||||||
    if not fan_status:
 | 
					 | 
				
			||||||
        return "<p>Failed to put headwind to sleep</p>", 503
 | 
					 | 
				
			||||||
    return "<p>Putting headwind to sleep</p>", 200
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@app.route("/speed/<int:speed>")
 | 
					 | 
				
			||||||
async def speed(speed):
 | 
					 | 
				
			||||||
    fan = Headwind(app, app.config["ADDRESS"])
 | 
					 | 
				
			||||||
    fan_status = await fan.manualSpeed(speed)
 | 
					 | 
				
			||||||
    if not fan_status:
 | 
					 | 
				
			||||||
        return f"<p>Failed to set headwind speed to {speed}</p>", 503
 | 
					 | 
				
			||||||
    return f"<p>Setting headwind speed to {speed}</p>", 200
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@app.route("/hr")
 | 
					 | 
				
			||||||
async def hr():
 | 
					 | 
				
			||||||
    fan = Headwind(app, app.config["ADDRESS"])
 | 
					 | 
				
			||||||
    fan_status = await fan.hr()
 | 
					 | 
				
			||||||
    if not fan_status:
 | 
					 | 
				
			||||||
        return "<p>Failed to set headwind to HR mode</p>", 503
 | 
					 | 
				
			||||||
    return "<p>Setting headwind to HR mode</p>", 200
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@app.route("/off")
 | 
					 | 
				
			||||||
async def off():
 | 
					 | 
				
			||||||
    fan = Headwind(app, app.config["ADDRESS"])
 | 
					 | 
				
			||||||
    fan_status = await fan.off()
 | 
					 | 
				
			||||||
    if not fan_status:
 | 
					 | 
				
			||||||
        return "<p>Failed to turn headwind off</p>", 503
 | 
					 | 
				
			||||||
    return "<p>Turning headwind off</p>", 200
 | 
					 | 
				
			||||||
							
								
								
									
										12
									
								
								bluewind/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								bluewind/__init__.py
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,12 @@
 | 
				
			||||||
 | 
					# Initialise flask
 | 
				
			||||||
 | 
					from flask import Flask
 | 
				
			||||||
 | 
					app = Flask(__name__)
 | 
				
			||||||
 | 
					app.config['SERVER_NAME'] = '0.0.0.0:5000'
 | 
				
			||||||
 | 
					app.config.from_prefixed_env()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Initialise the bluetooth stack
 | 
				
			||||||
 | 
					from bluewind import headwind
 | 
				
			||||||
 | 
					fan = headwind.Headwind(app, app.config["ADDRESS"])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Load the views
 | 
				
			||||||
 | 
					from bluewind import views
 | 
				
			||||||
| 
						 | 
					@ -11,6 +11,8 @@ MIN_SPEED = [0x2, 0x1]
 | 
				
			||||||
HALF_SPEED = [0x2, 0x32]
 | 
					HALF_SPEED = [0x2, 0x32]
 | 
				
			||||||
FULL_SPEED = [0x2, 0x64]
 | 
					FULL_SPEED = [0x2, 0x64]
 | 
				
			||||||
CHARACTERISTIC = "a026e038-0a7d-4ab3-97fa-f1500f9feb8b"
 | 
					CHARACTERISTIC = "a026e038-0a7d-4ab3-97fa-f1500f9feb8b"
 | 
				
			||||||
 | 
					# > read the above characteristic 0xFD-01-XX-04 where XX is speed 
 | 
				
			||||||
 | 
					# > bytearray(b'\xfd\x01\x00\x01')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Headwind:
 | 
					class Headwind:
 | 
				
			||||||
    fanClient = None
 | 
					    fanClient = None
 | 
				
			||||||
| 
						 | 
					@ -19,7 +21,23 @@ class Headwind:
 | 
				
			||||||
        self.flaskApp = flaskApp
 | 
					        self.flaskApp = flaskApp
 | 
				
			||||||
        self.fanClient = BleakClient(address)
 | 
					        self.fanClient = BleakClient(address)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async def sleep(self):
 | 
					    async def readSpeed(self):
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            async with self.fanClient as client:
 | 
				
			||||||
 | 
					                result = await client.read_gatt_char(CHARACTERISTIC)
 | 
				
			||||||
 | 
					                return result[2]
 | 
				
			||||||
 | 
					        except Exception:
 | 
				
			||||||
 | 
					            return 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    async def readMode(self):
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            async with self.fanClient as client:
 | 
				
			||||||
 | 
					                result = await client.read_gatt_char(CHARACTERISTIC)
 | 
				
			||||||
 | 
					                return result[3] # Return state code, needs to figure out what each code means
 | 
				
			||||||
 | 
					        except Exception:
 | 
				
			||||||
 | 
					            return 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    async def writeSleep(self):
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            async with self.fanClient as client:
 | 
					            async with self.fanClient as client:
 | 
				
			||||||
                await client.write_gatt_char(CHARACTERISTIC, SLEEP)
 | 
					                await client.write_gatt_char(CHARACTERISTIC, SLEEP)
 | 
				
			||||||
| 
						 | 
					@ -27,7 +45,7 @@ class Headwind:
 | 
				
			||||||
        except Exception as e:
 | 
					        except Exception as e:
 | 
				
			||||||
            return False
 | 
					            return False
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    async def on(self):
 | 
					    async def writeOn(self):
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            async with self.fanClient as client:
 | 
					            async with self.fanClient as client:
 | 
				
			||||||
                await client.write_gatt_char(CHARACTERISTIC, ON)
 | 
					                await client.write_gatt_char(CHARACTERISTIC, ON)
 | 
				
			||||||
| 
						 | 
					@ -35,7 +53,7 @@ class Headwind:
 | 
				
			||||||
        except Exception as e:
 | 
					        except Exception as e:
 | 
				
			||||||
            return False
 | 
					            return False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async def speedMode(self):
 | 
					    async def writeSpeedMode(self):
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            async with self.fanClient as client:
 | 
					            async with self.fanClient as client:
 | 
				
			||||||
                await client.write_gatt_char(CHARACTERISTIC, SPD)
 | 
					                await client.write_gatt_char(CHARACTERISTIC, SPD)
 | 
				
			||||||
| 
						 | 
					@ -43,7 +61,7 @@ class Headwind:
 | 
				
			||||||
        except Exception as e:
 | 
					        except Exception as e:
 | 
				
			||||||
            return False
 | 
					            return False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async def hrMode(self):
 | 
					    async def writeHrMode(self):
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            async with self.fanClient as client:
 | 
					            async with self.fanClient as client:
 | 
				
			||||||
                await client.write_gatt_char(CHARACTERISTIC, HR)
 | 
					                await client.write_gatt_char(CHARACTERISTIC, HR)
 | 
				
			||||||
| 
						 | 
					@ -51,7 +69,7 @@ class Headwind:
 | 
				
			||||||
        except Exception as e:
 | 
					        except Exception as e:
 | 
				
			||||||
            return False
 | 
					            return False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async def manualSpeed(self, speed):
 | 
					    async def writeSpeed(self, speed):
 | 
				
			||||||
        if speed > 0:
 | 
					        if speed > 0:
 | 
				
			||||||
            value = [0x2, speed]
 | 
					            value = [0x2, speed]
 | 
				
			||||||
            try:
 | 
					            try:
 | 
				
			||||||
| 
						 | 
					@ -60,10 +78,9 @@ class Headwind:
 | 
				
			||||||
                    return True
 | 
					                    return True
 | 
				
			||||||
            except Exception as e:
 | 
					            except Exception as e:
 | 
				
			||||||
                return False
 | 
					                return False
 | 
				
			||||||
        else:
 | 
					        return False
 | 
				
			||||||
            return False
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async def off(self):
 | 
					    async def writeOff(self):
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            async with self.fanClient as client:
 | 
					            async with self.fanClient as client:
 | 
				
			||||||
                await client.write_gatt_char(CHARACTERISTIC, OFF)
 | 
					                await client.write_gatt_char(CHARACTERISTIC, OFF)
 | 
				
			||||||
| 
						 | 
					@ -15,4 +15,16 @@ service001e = "a026ee0c-0a7d-4ab3-97fa-f1500f9feb8b"                    # Vendor
 | 
				
			||||||
service001e_char001f = "a026e038-0a7d-4ab3-97fa-f1500f9feb8b"           # Vendor specific
 | 
					service001e_char001f = "a026e038-0a7d-4ab3-97fa-f1500f9feb8b"           # Vendor specific
 | 
				
			||||||
service001e_char001f_desc0021 = "00002902-0000-1000-8000-00805f9b34fb"  # Client Characteristic Configuration
 | 
					service001e_char001f_desc0021 = "00002902-0000-1000-8000-00805f9b34fb"  # Client Characteristic Configuration
 | 
				
			||||||
handle = 0x0000
 | 
					handle = 0x0000
 | 
				
			||||||
address = 'F2:B3:F7:6A:24:48'
 | 
					address = 'F2:B3:F7:6A:24:48'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# bytearray(b'\xfd\x01\x19\x04')
 | 
				
			||||||
 | 
					# 127.0.0.1 - - [10/Nov/2023 15:56:50] "GET /get/speed HTTP/1.1" 200 -
 | 
				
			||||||
 | 
					# 127.0.0.1 - - [10/Nov/2023 15:57:14] "GET /speed/32 HTTP/1.1" 200 -
 | 
				
			||||||
 | 
					# bytearray(b'\xfd\x01 \x04')
 | 
				
			||||||
 | 
					# 127.0.0.1 - - [10/Nov/2023 15:57:23] "GET /get/speed HTTP/1.1" 200 -
 | 
				
			||||||
 | 
					# 127.0.0.1 - - [10/Nov/2023 15:58:01] "GET /speed/50 HTTP/1.1" 200 -
 | 
				
			||||||
 | 
					# bytearray(b'\xfd\x012\x04')
 | 
				
			||||||
 | 
					# 127.0.0.1 - - [10/Nov/2023 15:58:14] "GET /get/speed HTTP/1.1" 200 -
 | 
				
			||||||
 | 
					# 127.0.0.1 - - [10/Nov/2023 15:58:37] "GET /speed/100 HTTP/1.1" 200 -
 | 
				
			||||||
 | 
					# bytearray(b'\xfd\x01d\x04')
 | 
				
			||||||
 | 
					# 127.0.0.1 - - [10/Nov/2023 15:58:45] "GET /get/speed HTTP/1.1" 200 -
 | 
				
			||||||
							
								
								
									
										80
									
								
								bluewind/views.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										80
									
								
								bluewind/views.py
									
									
									
									
									
										Executable file
									
								
							| 
						 | 
					@ -0,0 +1,80 @@
 | 
				
			||||||
 | 
					#!/usr/bin/env python3
 | 
				
			||||||
 | 
					from bluewind import app, fan
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@app.route("/on", methods=["POST"])
 | 
				
			||||||
 | 
					async def setOn():
 | 
				
			||||||
 | 
					    fan_status = await fan.writeOn()
 | 
				
			||||||
 | 
					    if not fan_status:
 | 
				
			||||||
 | 
					        return "Failed to turn headwind on", 503
 | 
				
			||||||
 | 
					    return "Turning headwind on", 200
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@app.route("/sleep", methods=["POST"])
 | 
				
			||||||
 | 
					async def setSleep():
 | 
				
			||||||
 | 
					    fan_status = await fan.writeSleep()
 | 
				
			||||||
 | 
					    if not fan_status:
 | 
				
			||||||
 | 
					        return "Failed to put headwind to sleep", 503
 | 
				
			||||||
 | 
					    return "Putting headwind to sleep", 200
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@app.route("/speed/<int:speed>", methods=["POST"])
 | 
				
			||||||
 | 
					async def setSpeed(speed):
 | 
				
			||||||
 | 
					    fan_status = await fan.writeSpeed(speed)
 | 
				
			||||||
 | 
					    if not fan_status:
 | 
				
			||||||
 | 
					        return f"Failed to set headwind speed to {speed}", 503
 | 
				
			||||||
 | 
					    return f"Setting headwind speed to {speed}", 200
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@app.route("/speed/increase", methods=["POST"])
 | 
				
			||||||
 | 
					async def setIncreaseSpeed():
 | 
				
			||||||
 | 
					    print("increase speed")
 | 
				
			||||||
 | 
					    currentSpeed = await fan.readSpeed()
 | 
				
			||||||
 | 
					    newSpeed = 0
 | 
				
			||||||
 | 
					    if currentSpeed < 25:
 | 
				
			||||||
 | 
					        newSpeed = 25
 | 
				
			||||||
 | 
					    elif currentSpeed < 50:
 | 
				
			||||||
 | 
					        newSpeed = 50
 | 
				
			||||||
 | 
					    elif currentSpeed < 75:
 | 
				
			||||||
 | 
					        newSpeed = 75
 | 
				
			||||||
 | 
					    elif currentSpeed < 100:
 | 
				
			||||||
 | 
					        newSpeed = 100
 | 
				
			||||||
 | 
					    fan_status = await fan.writeSpeed(newSpeed)
 | 
				
			||||||
 | 
					    if not fan_status:
 | 
				
			||||||
 | 
					        return f"Failed to increase speed by 25%", 503
 | 
				
			||||||
 | 
					    return f"Increased speed by 25%", 200
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@app.route("/speed/decrease", methods=["POST"])
 | 
				
			||||||
 | 
					async def setDecreaseSpeed():
 | 
				
			||||||
 | 
					    print("decrease speed")
 | 
				
			||||||
 | 
					    currentSpeed = await fan.readSpeed()
 | 
				
			||||||
 | 
					    newSpeed = 0
 | 
				
			||||||
 | 
					    if currentSpeed == 100:
 | 
				
			||||||
 | 
					        newSpeed = 75
 | 
				
			||||||
 | 
					    elif currentSpeed >= 75:
 | 
				
			||||||
 | 
					        newSpeed = 50
 | 
				
			||||||
 | 
					    elif currentSpeed >= 50:
 | 
				
			||||||
 | 
					        newSpeed = 25
 | 
				
			||||||
 | 
					    elif currentSpeed > 25:
 | 
				
			||||||
 | 
					        newSpeed = 25
 | 
				
			||||||
 | 
					    elif currentSpeed <= 25:
 | 
				
			||||||
 | 
					        newSpeed = 1
 | 
				
			||||||
 | 
					    fan_status = await fan.writeSpeed(newSpeed)
 | 
				
			||||||
 | 
					    if not fan_status:
 | 
				
			||||||
 | 
					        return f"Failed to decrease speed by 25%", 503
 | 
				
			||||||
 | 
					    return f"Decreased speed by 25%", 200
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@app.route("/speed", methods=["GET"])
 | 
				
			||||||
 | 
					async def getSpeed():
 | 
				
			||||||
 | 
					    speed = await fan.readSpeed()
 | 
				
			||||||
 | 
					    return f"{speed}", 200
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@app.route("/hr", methods=["POST"])
 | 
				
			||||||
 | 
					async def setHr():
 | 
				
			||||||
 | 
					    fan_status = await fan.writeHr()
 | 
				
			||||||
 | 
					    if not fan_status:
 | 
				
			||||||
 | 
					        return "Failed to set headwind to HR mode", 503
 | 
				
			||||||
 | 
					    return "Setting headwind to HR mode", 200
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@app.route("/off", methods=["POST"])
 | 
				
			||||||
 | 
					async def setOff():
 | 
				
			||||||
 | 
					    fan_status = await fan.off()
 | 
				
			||||||
 | 
					    if not fan_status:
 | 
				
			||||||
 | 
					        return "Failed to turn headwind off", 503
 | 
				
			||||||
 | 
					    return "Turning headwind off", 200
 | 
				
			||||||
| 
						 | 
					@ -1,12 +0,0 @@
 | 
				
			||||||
class Configurinator:
 | 
					 | 
				
			||||||
    address = ""
 | 
					 | 
				
			||||||
    cmd = ""
 | 
					 | 
				
			||||||
    speed = ""
 | 
					 | 
				
			||||||
 
 | 
					 | 
				
			||||||
    def __init__(self):
 | 
					 | 
				
			||||||
        pass
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def load_config(self, address, cmd, speed):
 | 
					 | 
				
			||||||
        self.address = address
 | 
					 | 
				
			||||||
        self.cmd = cmd
 | 
					 | 
				
			||||||
        self.speed = speed
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1 +1,2 @@
 | 
				
			||||||
FLASK_ADDRESS='F2:B3:F7:6A:24:48'
 | 
					FLASK_ADDRESS='F2:B3:F7:6A:24:48'
 | 
				
			||||||
 | 
					FLASK_URL='127.0.0.1:5000'
 | 
				
			||||||
							
								
								
									
										33
									
								
								main.py
									
									
									
									
									
								
							
							
						
						
									
										33
									
								
								main.py
									
									
									
									
									
								
							| 
						 | 
					@ -1,32 +1,5 @@
 | 
				
			||||||
#!/usr/bin/env python3
 | 
					#!/usr/bin/env python3
 | 
				
			||||||
import asyncio
 | 
					from bluewind import app
 | 
				
			||||||
import click
 | 
					 | 
				
			||||||
from config import Configurinator as Config
 | 
					 | 
				
			||||||
from headwind import Headwind as Headwind
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
@click.command()
 | 
					if __name__ == '__main__':
 | 
				
			||||||
@click.option('--address', default=None, help='headwind mac address')
 | 
					    app.run(debug=False)
 | 
				
			||||||
@click.option('--cmd', default=None, help='command to send')
 | 
					 | 
				
			||||||
@click.option('--speed', default=1, help='manual speed value, 1 to 100')
 | 
					 | 
				
			||||||
def main(address, cmd, speed):
 | 
					 | 
				
			||||||
    conf = Config()
 | 
					 | 
				
			||||||
    conf.load_config(address, cmd, speed)
 | 
					 | 
				
			||||||
    asyncio.run(bluewind(conf))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
async def bluewind(conf):
 | 
					 | 
				
			||||||
    fan = Headwind(conf.address)
 | 
					 | 
				
			||||||
    match conf.cmd:
 | 
					 | 
				
			||||||
        case 'on':
 | 
					 | 
				
			||||||
            print("turning fan on")
 | 
					 | 
				
			||||||
            await fan.on()
 | 
					 | 
				
			||||||
        case 'sleep':
 | 
					 | 
				
			||||||
            print("putting fan to sleep")
 | 
					 | 
				
			||||||
            await fan.sleep()
 | 
					 | 
				
			||||||
        case 'manual':
 | 
					 | 
				
			||||||
            print("setting fan speed")
 | 
					 | 
				
			||||||
            await fan.speed(conf.speed)
 | 
					 | 
				
			||||||
    print('stuff')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
if __name__ == "__main__":
 | 
					 | 
				
			||||||
    main()
 | 
					 | 
				
			||||||
							
								
								
									
										31
									
								
								scripts/install.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								scripts/install.sh
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,31 @@
 | 
				
			||||||
 | 
					#!/bin/bash
 | 
				
			||||||
 | 
					# Export the environment variables
 | 
				
			||||||
 | 
					if [ ! -f ".env" ]; then
 | 
				
			||||||
 | 
					  echo "The .env file does not exist, please make a copy of default.env into .env and adjust its contents before proceeding."
 | 
				
			||||||
 | 
					  exit 1
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					export $(cat .env)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Create new systemd file
 | 
				
			||||||
 | 
					touch /etc/systemd/system/bluewind.service
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Fill in the systemd file
 | 
				
			||||||
 | 
					echo -e """[Unit]
 | 
				
			||||||
 | 
					Description=Flask Application
 | 
				
			||||||
 | 
					After=multi-user.target
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[Service]
 | 
				
			||||||
 | 
					Type=simple
 | 
				
			||||||
 | 
					ExecStart=$(pwd)/.venv/bin/python3 $(pwd)/main.py
 | 
				
			||||||
 | 
					Restart=always
 | 
				
			||||||
 | 
					Environment="FLASK_ADDRESS=$(echo $FLASK_ADDRESS)"
 | 
				
			||||||
 | 
					Environment="FLASK_URL=$(echo $FLASK_URL)"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[Install]
 | 
				
			||||||
 | 
					WantedBy=multi-user.target
 | 
				
			||||||
 | 
					""" > /etc/systemd/system/bluewind.service
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Reload systemd unit, start and enable the service
 | 
				
			||||||
 | 
					systemctl daemon-reload
 | 
				
			||||||
 | 
					systemctl enable bluewind.service
 | 
				
			||||||
 | 
					systemctl start bluewind.service
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user