Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
111 changes: 111 additions & 0 deletions Drivers/button_control/button_control.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
#!/usr/bin/env python3

"""
Renamed folder & file
Move onto Pi
Delete old files
give permissions to new files
"""

import os
import sys
import paho.mqtt.client as mqtt
import RPi.GPIO as GPIO
import time
import json
from argparse import ArgumentParser
import logging

# append this file's directory to path
root_folder = os.path.abspath(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
sys.path.append(root_folder)

from lib.mqtt_client import MQTTClient

# set up logging
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)

logger_formatter = logging.Formatter('%(levelname)s:%(name)s:%(message)s')

logger_file_handler = logging.FileHandler('turning_control.log') # TODO: setup a logging folder and write all logging files to that folder
logger_file_handler.setFormatter(logger_formatter)

logger_stream_handler = logging.StreamHandler() # this will print all logs to the terminal also

logger.addHandler(logger_file_handler)
logger.addHandler(logger_stream_handler)

# define pins
RIGHT_PIN = 11
LEFT_PIN = 12
BREAK_PIN = 15

# get MQTT credentials from passed values
parser = ArgumentParser(description="Bike turning controller")
parser.add_argument('--broker_address', dest='broker_address', default=os.getenv('MQTT_HOSTNAME'), type=str, help='The MQTT broker address getting from HiveMQ Cloud')
parser.add_argument('--username', dest='username', default=os.getenv('MQTT_USERNAME'), type=str, help='MQTT username')
parser.add_argument('--password', dest='password', default=os.getenv('MQTT_PASSWORD'), type=str, help='MQTT password')
parser.add_argument('--port', dest='port', default=os.getenv('MQTT_PORT'), type=int, help='MQTT broker port')
parser.add_argument('--device_id', dest='device_id', default=os.getenv('DEVICE_ID'), type=str, help="Bike's unique id")
parser.add_argument('--button_topic', dest='button_topic', default=f"bike/{os.getenv('DEVICE_ID')}/button", help='MQTT topic for activity of the buttons on the bike')
args = parser.parse_args()

class Button():

def __init__(self, pin: int, name: str, client: MQTTClient):

# define properties
self._pin = pin
self._name = name
self._client = client
self._state = 0
self._topic = args.button_topic
self._control_topic = args.button_topic + '/report'

# set up pin & callbacks
GPIO.setup(self._pin, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.add_event_detect(self._pin, GPIO.BOTH, callback=self.state_change, bouncetime=200)

logger.info(f'initialised {self._name} button')

def state_change(self, pin: int):
"""the callback passes the pin for some reason."""
# grab the current state
self._state = GPIO.input(self._pin)

# publish to MQTT
payload = json.dumps({'button' : self._name, 'state' : self._state, 'timestamp' : time.time()})
self._client.publish(self._control_topic, payload)

# log the change
if self._state == 0:
logger.debug(f'{self._name} button released')
elif self._state == 1:
logger.debug(f'{self._name} button pressed')

def main():
# set up MQTT client
client = MQTTClient(args.broker_address, args.username, args.password, port=args.port)
client.setup_mqtt_client()

# set up GPIO
GPIO.setmode(GPIO.BOARD)

# create buttons
left_button = Button(LEFT_PIN, 'LEFT', client)
right_button = Button(RIGHT_PIN, 'RIGHT', client)
break_button = Button(BREAK_PIN, 'BREAK', client)

# loop until terminated
# TODO: is this actually ok to do?
try:
while True:
pass

except KeyboardInterrupt:
GPIO.cleanup()
#client.disconnect()

if __name__=="__main__":
main()
Empty file added Drivers/lib/__init__.py
Empty file.
33 changes: 25 additions & 8 deletions Drivers/lib/mqtt_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,30 @@
import time
import paho.mqtt.client as paho
from paho import mqtt
import logging

# setup logging

logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)

logger_formatter = logging.Formatter('%(levelname)s:%(name)s:%(message)s')

logger_file_handler = logging.FileHandler('mqtt.log') # TODO: setup a logging folder and write all logging files to that folder
logger_file_handler.setFormatter(logger_formatter)

logger_stream_handler = logging.StreamHandler() # this will print all logs to the terminal also

logger.addHandler(logger_file_handler)
logger.addHandler(logger_stream_handler)

# this is a MQTT client that is able to publish to and subscribe from MQTT topics in HiveMQ Cloud
class MQTTClient:
def __init__(self, broker_address, username, password):
def __init__(self, broker_address, username, password, port=1883):
self.broker_address = broker_address
self.username = username
self.password = password
self.port = port
self.client = None

def get_client(self):
Expand All @@ -23,11 +40,11 @@ def setup_mqtt_client(self):
self.client.on_connect = self.on_connect

# enable TLS for secure connection
self.client.tls_set(tls_version=mqtt.client.ssl.PROTOCOL_TLS)
self.client.tls_set(tls_version=paho.ssl.PROTOCOL_TLS)
# set username and password
self.client.username_pw_set(self.username, self.password)
# connect to HiveMQ Cloud on port 8883 (default for MQTT)
self.client.connect(self.broker_address, 8883)
self.client.connect(self.broker_address, self.port)

# setting callbacks, use separate functions like above for better visibility
self.client.on_subscribe = self.on_subscribe
Expand All @@ -54,20 +71,20 @@ def loop_start(self):

# setting callbacks for different events to see if it works, print the message etc.
def on_connect(self, client, userdata, flags, rc, properties=None):
print("CONNACK received with code %s." % rc)
logger.info("CONNACK received with code %s." % rc)

# with this callback you can see if your publish was successful
def on_publish(self, client, userdata, mid, properties=None):
print("[MQTT message published] mid: " + str(mid))
logger.info("[MQTT message published] mid: " + str(mid))

# print which topic was subscribed to
def on_subscribe(self, client, userdata, mid, granted_qos, properties=None):
print("Subscribed: " + str(mid) + " " + str(granted_qos))
logger.info("Subscribed: " + str(mid) + " " + str(granted_qos))

# print message, useful for checking if it was successful
def on_message(self, client, userdata, msg):
print(msg.topic + " " + str(msg.qos) + " " + str(msg.payload))
logger.info(msg.topic + " " + str(msg.qos) + " " + str(msg.payload))

def on_disconnect(self, client, userdata,rc=0):
self.client.logging.debug(f"Disconnected result code: {str(rc)}")
self.client.loop_stop()
self.client.loop_stop()
25 changes: 25 additions & 0 deletions Drivers/pico_remote/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Description:
This device interacts with the wahoo kickr and climbr via the Raspberry Pi 000001, located in the IoT lab, building M.102.
Its intention is to manipulate the hardware in real-time without the need for running or accessing third-party software such as the mobile app, VR, or other interfaces.
The purpose of this is that it allows users to simply use the bike with a simple interface.

# How to Run:
- Kickr script (/iot/scripts/./start_kickr.sh) must be executed and successful connection between Pi and Kickr must be established for this device to work as intended.
- Turn on remote device by pushing the white button on the power regulator on the top of the breadboard
- BT module should be flashing red while waiting for pairing.
- Navigate to iot/Drivers/pico_remote and execute the script via 'python3 pico_bt_handler.py' to run the handler.
- successful connection is determined by the HC-06 module turning into a solid red light.
- Upon successful connection between the HC-06 Bluetooth module and the Raspberry pi, you may now interact with the hardware via the push buttons:

### Note: You must press and hold the selected button in order to influence hardware.

# Buttons:
### Button 1: increase resistance
### Button 2: decrease resistance
### Button 3: increase incline
### Button 4: decrease incline

![Screenshot 2023-09-24 142627](https://github.com/redbackoperations/iot/assets/69894063/d3f90db2-0b68-41e7-b8c1-3ca8d65c8ad4)
![WIN_20230924_12_03_43_Pro](https://github.com/redbackoperations/iot/assets/69894063/0cd708ff-146f-48b0-ac11-f858ef215387)
![WIN_20230924_12_03_08_Pro](https://github.com/redbackoperations/iot/assets/69894063/91f63b5b-432b-4208-a054-40ffb96bd527)

3 changes: 3 additions & 0 deletions scripts/start_button_control.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
source ~/.env

python3 ~/iot/Drivers/button_control/button_control.py