From a156c46015dc873ee55e28e7bd0a37368dd8fcb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Fr=C4=85tczak?= Date: Fri, 10 Nov 2023 23:30:00 +0100 Subject: [PATCH 1/7] add read mode --- api.py | 50 +++++++++++++++++++++++++------------------- headwind/__init__.py | 30 ++++++++++++++++++++------ headwind/spec.py | 14 ++++++++++++- 3 files changed, 65 insertions(+), 29 deletions(-) diff --git a/api.py b/api.py index 97729c3..c239878 100755 --- a/api.py +++ b/api.py @@ -5,42 +5,48 @@ from headwind import Headwind as Headwind app = Flask(__name__) app.config.from_prefixed_env() -@app.route("/on") +@app.route("/on", methods=["POST"]) async def on(): fan = Headwind(app, app.config["ADDRESS"]) - fan_status = await fan.on() + fan_status = await fan.writeOn() if not fan_status: - return "

Failed to turn headwind on

", 503 - return "

Turning headwind on

", 200 + return "Failed to turn headwind on", 503 + return "Turning headwind on", 200 -@app.route("/sleep") +@app.route("/sleep", methods=["POST"]) async def sleep(): fan = Headwind(app, app.config["ADDRESS"]) - fan_status = await fan.sleep() + fan_status = await fan.writeSleep() if not fan_status: - return "

Failed to put headwind to sleep

", 503 - return "

Putting headwind to sleep

", 200 + return "Failed to put headwind to sleep", 503 + return "Putting headwind to sleep", 200 -@app.route("/speed/") +@app.route("/speed/", methods=["POST"]) async def speed(speed): fan = Headwind(app, app.config["ADDRESS"]) - fan_status = await fan.manualSpeed(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 + return f"Failed to set headwind speed to {speed}", 503 + return f"Setting headwind speed to {speed}", 200 -@app.route("/hr") -async def hr(): +@app.route("/speed", methods=["GET"]) +async def getSpeed(): fan = Headwind(app, app.config["ADDRESS"]) - fan_status = await fan.hr() - if not fan_status: - return "

Failed to set headwind to HR mode

", 503 - return "

Setting headwind to HR mode

", 200 + speed = await fan.readSpeed() + return f"{speed}", 200 -@app.route("/off") -async def off(): +@app.route("/hr", methods=["POST"]) +async def writeHr(): + fan = Headwind(app, app.config["ADDRESS"]) + 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 writeOff(): fan = Headwind(app, app.config["ADDRESS"]) fan_status = await fan.off() if not fan_status: - return "

Failed to turn headwind off

", 503 - return "

Turning headwind off

", 200 \ No newline at end of file + return "Failed to turn headwind off", 503 + return "Turning headwind off", 200 \ No newline at end of file diff --git a/headwind/__init__.py b/headwind/__init__.py index a2cb260..c5778df 100644 --- a/headwind/__init__.py +++ b/headwind/__init__.py @@ -11,6 +11,8 @@ MIN_SPEED = [0x2, 0x1] HALF_SPEED = [0x2, 0x32] FULL_SPEED = [0x2, 0x64] 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: fanClient = None @@ -19,7 +21,23 @@ class Headwind: self.flaskApp = flaskApp 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 + except Exception: + return 0 + + async def writeSleep(self): try: async with self.fanClient as client: await client.write_gatt_char(CHARACTERISTIC, SLEEP) @@ -27,7 +45,7 @@ class Headwind: except Exception as e: return False - async def on(self): + async def writeOn(self): try: async with self.fanClient as client: await client.write_gatt_char(CHARACTERISTIC, ON) @@ -35,7 +53,7 @@ class Headwind: except Exception as e: return False - async def speedMode(self): + async def writeSpeedMode(self): try: async with self.fanClient as client: await client.write_gatt_char(CHARACTERISTIC, SPD) @@ -43,7 +61,7 @@ class Headwind: except Exception as e: return False - async def hrMode(self): + async def writeHrMode(self): try: async with self.fanClient as client: await client.write_gatt_char(CHARACTERISTIC, HR) @@ -51,7 +69,7 @@ class Headwind: except Exception as e: return False - async def manualSpeed(self, speed): + async def writeSpeed(self, speed): if speed > 0: value = [0x2, speed] try: @@ -63,7 +81,7 @@ class Headwind: else: return False - async def off(self): + async def writeOff(self): try: async with self.fanClient as client: await client.write_gatt_char(CHARACTERISTIC, OFF) diff --git a/headwind/spec.py b/headwind/spec.py index 1b3ed14..aafc64c 100644 --- a/headwind/spec.py +++ b/headwind/spec.py @@ -15,4 +15,16 @@ service001e = "a026ee0c-0a7d-4ab3-97fa-f1500f9feb8b" # Vendor service001e_char001f = "a026e038-0a7d-4ab3-97fa-f1500f9feb8b" # Vendor specific service001e_char001f_desc0021 = "00002902-0000-1000-8000-00805f9b34fb" # Client Characteristic Configuration handle = 0x0000 -address = 'F2:B3:F7:6A:24:48' \ No newline at end of file +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 - \ No newline at end of file From eb4a70a7b157ed891a0bd9d3c7495d108af7c3fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Fr=C4=85tczak?= Date: Mon, 13 Nov 2023 23:15:12 +0100 Subject: [PATCH 2/7] refactor the application structure --- .gitignore | 5 +-- bluewind/__init__.py | 11 ++++++ {headwind => bluewind/headwind}/__init__.py | 40 +++++++++++++++++++++ {headwind => bluewind/headwind}/spec.py | 0 api.py => bluewind/views.py | 22 ++++-------- bootstrap.sh | 5 +++ config/__init__.py | 12 ------- main.py | 32 +---------------- 8 files changed, 64 insertions(+), 63 deletions(-) create mode 100644 bluewind/__init__.py rename {headwind => bluewind/headwind}/__init__.py (63%) rename {headwind => bluewind/headwind}/spec.py (100%) rename api.py => bluewind/views.py (67%) create mode 100644 bootstrap.sh delete mode 100644 config/__init__.py diff --git a/.gitignore b/.gitignore index a6b7ba4..5e49b42 100644 --- a/.gitignore +++ b/.gitignore @@ -158,7 +158,4 @@ cython_debug/ # 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 # option (not recommended) you can uncomment the following to ignore the entire idea folder. -#.idea/ - -bluewind -bluewind/* \ No newline at end of file +#.idea/ \ No newline at end of file diff --git a/bluewind/__init__.py b/bluewind/__init__.py new file mode 100644 index 0000000..afe7e90 --- /dev/null +++ b/bluewind/__init__.py @@ -0,0 +1,11 @@ +# Initialise flask +from flask import Flask +app = Flask(__name__) +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 \ No newline at end of file diff --git a/headwind/__init__.py b/bluewind/headwind/__init__.py similarity index 63% rename from headwind/__init__.py rename to bluewind/headwind/__init__.py index c5778df..4641273 100644 --- a/headwind/__init__.py +++ b/bluewind/headwind/__init__.py @@ -80,6 +80,46 @@ class Headwind: return False else: return False + + async def writeIncreaseSpeed(self): + try: + async with self.fanClient as client: + currentSpeed = await client.read_gatt_char(CHARACTERISTIC)[2] + newSpeed = 0 + if currentSpeed < 25: + newSpeed = 25 + elif currentSpeed < 50: + newSpeed = 50 + elif currentSpeed < 75: + newSpeed = 75 + elif currentSpeed < 100: + newSpeed = 100 + value = [0x2, newSpeed] + await client.write_gatt_char(CHARACTERISTIC, value) + return True + except Exception as e: + return False + + async def writeDecreaseSpeed(self): + try: + async with self.fanClient as client: + currentSpeed = await client.read_gatt_char(CHARACTERISTIC)[2] + 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: + return True + value = [0x2, newSpeed] + await client.write_gatt_char(CHARACTERISTIC, value) + return True + except Exception as e: + return False async def writeOff(self): try: diff --git a/headwind/spec.py b/bluewind/headwind/spec.py similarity index 100% rename from headwind/spec.py rename to bluewind/headwind/spec.py diff --git a/api.py b/bluewind/views.py similarity index 67% rename from api.py rename to bluewind/views.py index c239878..b18263e 100755 --- a/api.py +++ b/bluewind/views.py @@ -1,29 +1,22 @@ #!/usr/bin/env python3 -from flask import Flask -from headwind import Headwind as Headwind - -app = Flask(__name__) -app.config.from_prefixed_env() +from bluewind import app, fan @app.route("/on", methods=["POST"]) -async def on(): - fan = Headwind(app, app.config["ADDRESS"]) +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 sleep(): - fan = Headwind(app, app.config["ADDRESS"]) +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/", methods=["POST"]) -async def speed(speed): - fan = Headwind(app, app.config["ADDRESS"]) +async def setSpeed(speed): fan_status = await fan.writeSpeed(speed) if not fan_status: return f"Failed to set headwind speed to {speed}", 503 @@ -31,21 +24,18 @@ async def speed(speed): @app.route("/speed", methods=["GET"]) async def getSpeed(): - fan = Headwind(app, app.config["ADDRESS"]) speed = await fan.readSpeed() return f"{speed}", 200 @app.route("/hr", methods=["POST"]) -async def writeHr(): - fan = Headwind(app, app.config["ADDRESS"]) +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 writeOff(): - fan = Headwind(app, app.config["ADDRESS"]) +async def setOff(): fan_status = await fan.off() if not fan_status: return "Failed to turn headwind off", 503 diff --git a/bootstrap.sh b/bootstrap.sh new file mode 100644 index 0000000..cc759ad --- /dev/null +++ b/bootstrap.sh @@ -0,0 +1,5 @@ +#!/bin/bash +python3 -m venv .venv +source .venv/bin/activate +python3 -m pip install --upgrade pip +pip3 install -r requirements.txt \ No newline at end of file diff --git a/config/__init__.py b/config/__init__.py deleted file mode 100644 index cee1e6d..0000000 --- a/config/__init__.py +++ /dev/null @@ -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 diff --git a/main.py b/main.py index a0ad445..eaff4ae 100755 --- a/main.py +++ b/main.py @@ -1,32 +1,2 @@ #!/usr/bin/env python3 -import asyncio -import click -from config import Configurinator as Config -from headwind import Headwind as Headwind - -@click.command() -@click.option('--address', default=None, help='headwind mac address') -@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() \ No newline at end of file +from bluewind import bluewind \ No newline at end of file From 1c8980f3a518e7ac021ad6f727e3220cd6efe6f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Fr=C4=85tczak?= Date: Tue, 14 Nov 2023 18:22:27 +0100 Subject: [PATCH 3/7] working speed increase and decrease endpoints --- bluewind/headwind/__init__.py | 44 ++--------------------------------- bluewind/views.py | 38 ++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 42 deletions(-) diff --git a/bluewind/headwind/__init__.py b/bluewind/headwind/__init__.py index 4641273..2842ab8 100644 --- a/bluewind/headwind/__init__.py +++ b/bluewind/headwind/__init__.py @@ -75,51 +75,11 @@ class Headwind: try: async with self.fanClient as client: await client.write_gatt_char(CHARACTERISTIC, value) + # print("flag") return True except Exception as e: return False - else: - return False - - async def writeIncreaseSpeed(self): - try: - async with self.fanClient as client: - currentSpeed = await client.read_gatt_char(CHARACTERISTIC)[2] - newSpeed = 0 - if currentSpeed < 25: - newSpeed = 25 - elif currentSpeed < 50: - newSpeed = 50 - elif currentSpeed < 75: - newSpeed = 75 - elif currentSpeed < 100: - newSpeed = 100 - value = [0x2, newSpeed] - await client.write_gatt_char(CHARACTERISTIC, value) - return True - except Exception as e: - return False - - async def writeDecreaseSpeed(self): - try: - async with self.fanClient as client: - currentSpeed = await client.read_gatt_char(CHARACTERISTIC)[2] - 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: - return True - value = [0x2, newSpeed] - await client.write_gatt_char(CHARACTERISTIC, value) - return True - except Exception as e: - return False + return False async def writeOff(self): try: diff --git a/bluewind/views.py b/bluewind/views.py index b18263e..bd14bc3 100755 --- a/bluewind/views.py +++ b/bluewind/views.py @@ -22,6 +22,44 @@ async def setSpeed(speed): 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() From b1ba4810894560eea464f3e9170c614555a8d964 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Fr=C4=85tczak?= Date: Tue, 14 Nov 2023 19:05:44 +0100 Subject: [PATCH 4/7] starting work on docker image --- Dockerfile | 10 ++++++++++ bluewind/headwind/__init__.py | 3 +-- main.py | 5 ++++- 3 files changed, 15 insertions(+), 3 deletions(-) create mode 100644 Dockerfile diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..38d8f37 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,10 @@ +FROM --platform=$BUILDPLATFORM python:3.10-alpine AS builder + +WORKDIR /app + +COPY requirements.txt /app +RUN pip3 install -r requirements.txt + +COPY . /app + +CMD ["python", "main.py"] \ No newline at end of file diff --git a/bluewind/headwind/__init__.py b/bluewind/headwind/__init__.py index 2842ab8..19d955c 100644 --- a/bluewind/headwind/__init__.py +++ b/bluewind/headwind/__init__.py @@ -33,7 +33,7 @@ class Headwind: try: async with self.fanClient as client: result = await client.read_gatt_char(CHARACTERISTIC) - return result[3] # Return state code + return result[3] # Return state code, needs to figure out what each code means except Exception: return 0 @@ -75,7 +75,6 @@ class Headwind: try: async with self.fanClient as client: await client.write_gatt_char(CHARACTERISTIC, value) - # print("flag") return True except Exception as e: return False diff --git a/main.py b/main.py index eaff4ae..72d2478 100755 --- a/main.py +++ b/main.py @@ -1,2 +1,5 @@ #!/usr/bin/env python3 -from bluewind import bluewind \ No newline at end of file +from bluewind import app + +if __name__ == '__main__': + app.run(debug=False) \ No newline at end of file From 91df8a0f26828eff60a9926c2d61c34a8e984142 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Fr=C4=85tczak?= Date: Tue, 14 Nov 2023 21:53:18 +0100 Subject: [PATCH 5/7] add server name flask param --- bluewind/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/bluewind/__init__.py b/bluewind/__init__.py index afe7e90..79e0781 100644 --- a/bluewind/__init__.py +++ b/bluewind/__init__.py @@ -1,6 +1,7 @@ # 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 6ba5cc6815d319c5e8da3b5a7b1dfc5df95a4134 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Fr=C4=85tczak?= Date: Tue, 14 Nov 2023 23:50:10 +0100 Subject: [PATCH 6/7] create the bootstrap script and update the README.md --- Dockerfile | 10 ---------- README.md | 22 ++++++++++++++++++++-- bootstrap.sh | 5 ----- default.env | 3 ++- scripts/install.sh | 31 +++++++++++++++++++++++++++++++ 5 files changed, 53 insertions(+), 18 deletions(-) delete mode 100644 Dockerfile delete mode 100644 bootstrap.sh create mode 100644 scripts/install.sh diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index 38d8f37..0000000 --- a/Dockerfile +++ /dev/null @@ -1,10 +0,0 @@ -FROM --platform=$BUILDPLATFORM python:3.10-alpine AS builder - -WORKDIR /app - -COPY requirements.txt /app -RUN pip3 install -r requirements.txt - -COPY . /app - -CMD ["python", "main.py"] \ No newline at end of file diff --git a/README.md b/README.md index 4e8e79e..ee4055e 100644 --- a/README.md +++ b/README.md @@ -6,10 +6,28 @@ Bluetooth control app for Wahoo Headwind. ## Usage -To run the flask app: +To run the flask app for development and testing: ```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='' -flask --app api run --host=0.0.0.0 +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 diff --git a/bootstrap.sh b/bootstrap.sh deleted file mode 100644 index cc759ad..0000000 --- a/bootstrap.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash -python3 -m venv .venv -source .venv/bin/activate -python3 -m pip install --upgrade pip -pip3 install -r requirements.txt \ No newline at end of file diff --git a/default.env b/default.env index f627499..eac4c0d 100644 --- a/default.env +++ b/default.env @@ -1 +1,2 @@ -FLASK_ADDRESS='F2:B3:F7:6A:24:48' \ No newline at end of file +FLASK_ADDRESS='F2:B3:F7:6A:24:48' +FLASK_URL='127.0.0.1:5000' \ No newline at end of file diff --git a/scripts/install.sh b/scripts/install.sh new file mode 100644 index 0000000..ddece06 --- /dev/null +++ b/scripts/install.sh @@ -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 \ No newline at end of file From ebeacd72ae486c6622e70eec4a44dee75c6a9d69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Fr=C4=85tczak?= Date: Tue, 14 Nov 2023 23:52:03 +0100 Subject: [PATCH 7/7] patch README --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index ee4055e..0acd1e1 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,7 @@ source .venv/bin/activate python3 -m pip install --upgrade pip pip3 install -r requirements.txt export FLASK_ADDRESS='' +export FLASK_URL='