Skip to content

Commit

Permalink
Merge pull request #3 from chrisgilldc/dev
Browse files Browse the repository at this point in the history
Control Icon Fix
  • Loading branch information
chrisgilldc authored Jun 27, 2024
2 parents b902c24 + fe8a28a commit 5b0550e
Show file tree
Hide file tree
Showing 25 changed files with 268 additions and 68 deletions.
8 changes: 0 additions & 8 deletions .idea/brickmaster2.iml

This file was deleted.

14 changes: 12 additions & 2 deletions circuitpy-code.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,19 @@

# Check for the WIFI HW environment setting.
try:
wifihw = os.getenv("WIFI_HW")
wifihw = os.getenv("BRICKMASTER_WIFI_HW")
print("Wireless hardware pre-defined as '{}'".format(wifihw))
except AttributeError:
print("Wireless hardware not specified, auto-determining.")
wifihw = brickmaster2.util.determine_wifi_hw()

# Check for a hostname
try:
hostname = os.getenv("CIRCUITPY_WEB_INSTANCE_NAME")
except AttributeError:
print("Hostname not available. Set with 'CIRCUITPY_WEB_INSTANCE_NAME' in 'settings.toml'.")
hostname = None

# Open the config file.
#TODO: Replace this with fancier config open logic.
print("Loading 'config.json'")
Expand All @@ -28,7 +36,8 @@
wifi_obj = brickmaster2.network.BM2WiFi(
ssid=os.getenv("CIRCUITPY_WIFI_SSID"),
password=os.getenv("CIRCUITPY_WIFI_PASSWORD"),
wifihw=wifihw
wifihw=wifihw,
hostname = hostname
)

# Create the BrickMaster2 Object.
Expand All @@ -46,6 +55,7 @@
except Exception as e:
print("Received unhandled exception - ")
traceback.print_exception(e)
print("Exception type: {}".format(type(e)))
print("Waiting for 30s before.")
time.sleep(30)
microcontroller.reset()
10 changes: 5 additions & 5 deletions examples/brickmaster2.service
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
[Unit]
Description=Brickmaster2 Control System
After=default.target
Requires=sys-subsystem-net-devices-wlan0.device
After=sys-subsystem-net-devices-wlan0.device

[Service]
Type=idle
WorkingDirectory=/home/pi/brickmaster2
ExecStart=/usr/bin/python3 /home/pi/brickmaster2/brickmaster2.py
Restart=always
Type=simple
Environment="PYTHONPATH=/home/pi/brickmaster2-main"
ExecStart=/usr/bin/python3 /home/pi/brickmaster2-main/brickmaster2/cli/bm2cli.py -c /home/pi/lego_capitol.json

[Install]
WantedBy=default.target
147 changes: 147 additions & 0 deletions hwconfigs/brickmasterXL.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
{
"system": {
"id": "brickmasterxl",
"name": "BrickmasterXL",
"log_level": "warning",
"ha":{
"area": ### Area name here is recommended but not required. ###
},
"mqtt": {
"broker": ### Broker hostname or IP ###
"user": ### MQTT Username ###,
"key": ### MQTT Password ###
}
},
"controls": [
{
"id": "1_5v",
"name": "Port 1 - 5v",
"type": "aw9523",
"addr": "0x58",
"pin": 11
},
{
"id": "2_5v",
"name": "Port 2 - 5v",
"type": "aw9523",
"addr": "0x58",
"pin": 10
},
{
"id": "3_5v",
"name": "Port 3 - 5v",
"type": "aw9523",
"addr": "0x58",
"pin": 9,
"disable": true
},
{
"id": "4_5v",
"name": "Port 4 - 5v",
"type": "aw9523",
"addr": "0x58",
"pin": 8,
"disable": true
},
{
"id": "5_9v",
"name": "Port 5 - 9v",
"type": "gpio",
"pin": "D5",
"invert": true,
"disable": false
},
{
"id": "6_9v",
"name": "Port 6 - 9v",
"type": "gpio",
"pin": "D6",
"invert": true,
"disable": false
},
{
"id": "7_9v",
"name": "Port 7 - 9v",
"type": "gpio",
"pin": "D7",
"invert": true,
"disable": true
},
{
"id": "8_9v",
"name": "Port 8 - 9v",
"type": "gpio",
"pin": "D8",
"invert": "true",
"disable": true
},
{
"id": "9_5v",
"name": "Port 9 - 5v",
"type": "aw9523",
"addr": "0x58",
"pin": 4,
"disable": true
},
{
"id": "10_5v",
"name": "Port 10 - 5v",
"type": "aw9523",
"addr": "0x58",
"pin": 3,
"disable": true
},
{
"id": "11_5v",
"name": "Port 11 - 5v",
"type": "aw9523",
"addr": "0x58",
"pin": 2,
"disable": true
},
{
"id": "12_5v",
"name": "Port 12 - 5v",
"type": "aw9523",
"addr": "0x58",
"pin": 1,
"disable": true
},
{
"id": "13_9v",
"name": "Port 13 - 9v",
"type": "gpio",
"pin": "D4",
"invert": true,
"disable": true
},
{
"id": "14_9v",
"name": "Port 14 - 9v",
"type": "gpio",
"pin": "D3",
"invert": true,
"disable": true
},
{
"id": "15_9v",
"name": "Port 15 - 9v",
"type": "gpio",
"pin": "D2",
"invert": true,
"disable": true
},
{
"id": "16_9v",
"name": "Port 16 - 9v",
"type": "gpio",
"pin": "D1",
"invert": true,
"disable": true
}
],
"displays": [
],
"scripts": {
}
}
36 changes: 36 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
[project]
name = "BrickMaster2"
dynamic = ["version"]
authors = [
{ name="Christopher Gill", email="[email protected]" },
]
description = "CobraBay Parking Guidance System"
readme = "README.md"
requires-python = ">=3.8"
dependencies = [
"adafruit-circuitpython-ht16k33",
"adafruit-circuitpython-logging",
"Adafruit-Blinka",
"netifaces2",
"paho-mqtt",
"psutil",
"pid"
]
classifiers = [
"Programming Language :: Python :: 3",
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
"Development Status :: 3 - Alpha",
"Topic :: Home Automation"
]

[project.urls]
Homepage = "https://github.com/chrisgilldc/cobrabay"
Issues = "https://github.com/chrisgilldc/cobrabay/issues"

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[tool.hatch.version]
path = "pkg/__about__.py"
2 changes: 1 addition & 1 deletion scripts/saturn5_full.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"id": "saturn5_full",
"name": "Saturn 5 Full Launch",
"name": "Saturn V Full Launch",
"type": "flight",
"run": "once",
"at_completion": "restore",
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
19 changes: 12 additions & 7 deletions brickmaster2/config.py → src/brickmaster2/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -218,16 +218,17 @@ def _validate_secrets(self):

def _validate_controls(self):
if not isinstance(self._config['controls'], list):
self._logger.critical('Controls not correctly defined. Must be a list of dictionaries.')
self._logger.critical('Config: Controls not correctly defined. Must be a list of dictionaries.')
return
i = 0
to_delete = []
while i < len(self._config['controls']):
self._logger.debug("Config: Validating control definition '{}'".format(self._config['controls'][i]))
# Check to see if required items are defined.
required_keys = ['id', 'type']
for key in required_keys:
if key not in self._config['controls'][i]:
self._logger.critical("Required control config option '{}' missing in control {}. Cannot configure!".
self._logger.critical("Config: Required control config option '{}' missing in control {}. Cannot configure!".
format(key, i+1))
to_delete.append(i)

Expand Down Expand Up @@ -257,14 +258,14 @@ def _validate_controls(self):
elif ctrltype == 'aw9523':
required_parameters = ['addr', 'pin']
else:
self._logger.error("Cannot set up control '{}', type '{}' is not supported.".format(i, ctrltype))
self._logger.error("Config: Cannot set up control '{}', type '{}' is not supported.".format(i, ctrltype))
to_delete.append(i)
i += 1
continue

for req_param in required_parameters:
if req_param not in self._config['controls'][i]:
self._logger.error("Cannot set up control '{}', no '{}' directive.".format(
self._logger.error("Config: Cannot set up control '{}', no '{}' directive.".format(
self._config['controls'][i]['name'], req_param))
to_delete.append(i)
i += 1
Expand All @@ -275,11 +276,15 @@ def _validate_controls(self):
'icon': 'mdi:toy-brick'
}
for param in optional_params:
self._logger.debug("Checking for optional parameter '{}'".format(param))
if param not in self._config['system']:
self._logger.warning("Option '{}' not found, using default '{}'".
self._logger.debug("Config: Checking for optional parameter '{}'".format(param))
if param not in self._config['controls'][i]:
self._logger.warning("Config: Option '{}' not found, using default '{}'".
format(param, optional_defaults[param]))
self._config['controls'][i][param] = optional_defaults[param]
else:
self._logger.debug("Config: Optional parameter '{}' set to '{}'".format(
param, self._config['controls'][i][param]
))

i += 1
# Make the to_delete list unique.
Expand Down
File renamed without changes.
1 change: 0 additions & 1 deletion brickmaster2/core.py → src/brickmaster2/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,6 @@ def run(self):
self._logger.debug("Core: Entering run loop.")
while True:
# Poll the network.
self._logger.debug("Core: Polling network.")
self._network.poll()

# If there's an active script, do it.
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
24 changes: 14 additions & 10 deletions brickmaster2/network/base.py → src/brickmaster2/network/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ def __init__(self, core, system_id, short_name, long_name, broker, mqtt_username
self._reconnect_timestamp = None
self._logger.debug("Network: Setting internal MQTT tracker False at startup.")
self._mqtt_connected = False
self._total_failures = 0

# List for commands received and to be passed upward.
self._upward_commands = []
Expand All @@ -106,6 +107,11 @@ def __init__(self, core, system_id, short_name, long_name, broker, mqtt_username
self._logger.info("Defined Client ID: {}".format(self._system_id))

self._setup_mqtt() # Create the MQTT Object, connect basic callbacks
# Setup the will.
# Set the last will prior to connecting.
self._logger.info("Creating last will.")
self._mc_will_set(topic="brickmaster2/" + self._short_name + "/connectivity",
payload='offline', qos=0, retain=True)

self._logger.info('Network: Initialization complete.')

Expand Down Expand Up @@ -156,7 +162,6 @@ def poll(self):
}

# If interface is up but broker is not connected, retry every 30s.
self._logger.debug(f"Network: MQTT connection status from BM2 Tracker is '{self._mqtt_connected}'")
if not self._mqtt_connected:
try_reconnect = False
# Has is been 30s since the previous attempt?
Expand All @@ -165,8 +170,6 @@ def poll(self):
self._logger.info("Network: 30s since previous MQTT connection attempt. Retrying...")
try_reconnect = True
self._reconnect_timestamp = time.monotonic()
else:
self._logger.debug("Network: Too soon to retry MQTT connection")
except TypeError:
try_reconnect = True
self._reconnect_timestamp = time.monotonic()
Expand Down Expand Up @@ -247,18 +250,20 @@ def _connect_mqtt(self):
:return:
"""
# Set the last will prior to connecting.
self._logger.info("Creating last will.")
self._mc_will_set(topic="brickmaster2/" + self._short_name + "/connectivity",
payload='offline', qos=0, retain=True)

self._logger.debug("Network: Attempting MQTT connection.")
try:
# Call the connection method. This gets overridden by a subclass if needed.
self._mc_connect(host=self._mqtt_broker, port=self._mqtt_port)
except Exception as e:
self._logger.warning("Could not connect to MQTT broker. Received exception '{}'".format(e))
self._logger.warning(f"Network: Could not connect to MQTT broker. {self._total_failures}/5 failures. Received exception '{e}'")
self._logger.debug(f"Network: Exception is type '{type(e)}', args is '{e.args}'")
self._total_failures += 1
if self._total_failures > 5:
self._logger.critical("Network: Too many network failures.")
raise
return False
# self._logger.debug("Network: MQTT connection attempt completed.")
self._logger.debug("Network: MQTT connection attempt completed.")

# Set the internal MQTT tracker to True. Surprisingly, the client doesn't have a way to track this itself!
# self._logger.debug("Network: Setting internal MQTT tracker True in '_connect_mqtt' call.")
Expand Down Expand Up @@ -435,7 +440,6 @@ def _pub_message(self, topic, message, force_repeat=False):
else:
outbound_message = message
# Make the client-specific call!

self._mc_publish(topic, outbound_message)

# Method studs to be overridden.
Expand Down
Loading

0 comments on commit 5b0550e

Please sign in to comment.