Compare commits

..

2 Commits

4 changed files with 28 additions and 269 deletions

View File

@ -97,16 +97,24 @@ async def set_full_matrix_on_ble(colorSeries):
colorSeries[24] = temp_color_12
# =====================================================================
# Ensure all characteristics are available before writing
if len(ble_characteristics) != lampAmount:
print(f"Mismatch in lamp amount. Expected {lampAmount}, got {len(ble_characteristics)}.")
return
print(f"Constructed the following matrix data: {colorSeries}")
# Write each byte string to its corresponding characteristic
for i, char in enumerate(ble_characteristics):
value_to_write = colorSeries[i]
print(f"Setting Lamp {i} ({char.uuid}) to {value_to_write.hex()}")
await ble_client.write_gatt_char(char.uuid, value_to_write)
if DEBUG_MODE:
# Ensure all characteristics are available before writing
print(f"Confirmed DEBUG set to true.")
if len(ble_characteristics) != lampAmount:
print(f"Mismatch in lamp amount. Expected {lampAmount}, got {len(ble_characteristics)}.")
return
print(f"Constructed the following matrix data: {colorSeries}")
# Write each byte string to its corresponding characteristic
for i, char in enumerate(ble_characteristics):
value_to_write = colorSeries[i]
print(f"Setting Lamp {i} ({char.uuid}) to {value_to_write.hex()}")
await ble_client.write_gatt_char(char.uuid, value_to_write)
else:
print(f"Confirmed DEBUG set to false.")
value_to_write = b"".join([color for color in colorSeries])
print(value_to_write)
print(f"Setting lamps to {value_to_write.hex()}")
await ble_client.write_gatt_char(ble_characteristics[0].uuid, value_to_write)
async def connect_to_ble_device():

View File

@ -1,118 +0,0 @@
import asyncio
import time
from bleak import BleakScanner, BleakClient
lampAmount = 25
LampArray = {
"Center": [0],
"Up": [1,2,8,9,10,11,12,13,23,24],
"Down": [4,5,6,15,16,17,18,19,20,21],
"Left": [6,3,8,9,19,20,21,22,23,12],
"Right": [2,7,4,11,24,13,14,15,16,17],
"Inner": [1,2,3,4,5,6,7,8],
"Outer": [9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24]
}
colorArray = ["500000","005000","000050"]
colorArrayTest = ["050000","000500"]
def sectionInitializer():
result = [b'\x00\x00\x00'] * lampAmount
return result
def sectionSerializer(section, color):
result = sectionInitializer()
sectionResult = LampArray[section]
for pos in sectionResult:
result[pos] = int(color,16).to_bytes(3,'big')
return result
def posColorByte(pos, section, color):
intColor = int(color, 16)
result = int(intColor * section[pos])
print(result)
return result.to_bytes(3)
async def setOnUserInput(client, chars):
while True:
configZone = input("Input Zone [Up, Down, Left, Right, Inner, Outer]: ")
if configZone not in list(LampArray.keys()):
continue
configColor = input("Input Color [000000]: ")
configColorCenter = input("Input Color for Center Lamp [000000]: ")
await setLampToColor(client, chars, configZone, configColor, configColorCenter)
async def setLampToColor(bleClient, bleChars, section, color, colorCenter):
sectionSerial = sectionSerializer(section, color)
sectionSerial[0] = int(colorCenter,16).to_bytes(3,'big')
for char in bleChars:
lampPos = bleChars.index(char)
value = sectionSerial[lampPos]
print(f"Setting Lamp number {lampPos} to {value}")
await bleClient.write_gatt_char(char.uuid, value)
async def connect_to_ble_device(device_name):
print(f"Scanning for device: {device_name}...")
devices = await BleakScanner.discover()
global services
global client
target_device = None
for device in devices:
if device.name == device_name:
target_device = device
break
if target_device:
print(f"Found device: {target_device.name} ({target_device.address})")
async with BleakClient(target_device.address) as client:
if client.is_connected:
print(f"Connected to {target_device.name}")
# Now you can interact with services and characteristics
# Example: Read a characteristic (replace with actual UUID)
# battery_level = await client.read_gatt_char("00002a19-0000-1000-8000-00805f9b34fb")
# print(f"Battery Level: {int.from_bytes(battery_level, 'little')}%")
else:
print(f"Failed to connect to {target_device.name}")
exit(1)
services = sorted(client.services, key=lambda serv: serv.handle)
print("\n--- Services and Characteristics ---")
for service in services:
print(f"\nService: {service.uuid} (Handle: {service.handle}) - {service.description}")
# Get all characteristics for the current service
characteristics = service.characteristics
# Sort the characteristics by handle
sorted_characteristics = sorted(characteristics, key=lambda char: char.handle)
print("Characteristics sorted by handle:")
for char in sorted_characteristics:
print(f" Characteristic: {char.uuid} (Handle: {char.handle})")
print(f" Description: {char.description}")
print(f" Properties: {char.properties}")
if "read" in char.properties:
try:
await client.write_gatt_char(char.uuid, bytes.fromhex("000005"))
time.sleep(1)
value = await client.read_gatt_char(char.uuid)
print(f" Value: {value.hex()} (raw bytes)")
except Exception as e:
print(f" Could not read characteristic {char.uuid}: {e}")
else:
print(" (Read not supported)")
# for color in colorArray:
# await setLampToColor(client, service.characteristics, Up, color)
# await setLampToColor(client, service.characteristics, Down, color)
# await setLampToColor(client, service.characteristics, Left, color)
# await setLampToColor(client, service.characteristics, Right, color)
# await setLampToColor(client, service.characteristics, Inner, color)
# await setLampToColor(client, service.characteristics, Outer, color)
if service.handle != 1:
await setOnUserInput(client, sorted_characteristics)
else:
print(f"Device '{device_name}' not found.")
if __name__ == "__main__":
# Replace 'YourDeviceName' with the actual name of your BLE device
asyncio.run(connect_to_ble_device("Pupilometer LED Billboard"))

View File

@ -1,130 +0,0 @@
from flask import Flask, render_template, request, jsonify
# ... (paste the two helper functions here if they are not already present) ...
app = Flask(__name__)
def create_spiral_map(n=5):
"""
Creates a pre-computed spiral mapping for an n x n matrix.
The spiral starts from the center, moves up, then right, and spirals outwards.
Args:
n (int): The size of the square matrix.
Returns:
list of lists: A 2D list where each element is the spiraling address.
"""
if n % 2 == 0:
raise ValueError("Matrix size must be odd for a unique center point.")
spiral_map = [[0] * n for _ in range(n)]
# Starting position and index
r, c = n // 2, n // 2
address = 0
spiral_map[r][c] = address
# Directions: Up, Right, Down, Left
# This is the key change to adjust the spiral path
dr = [-1, 0, 1, 0]
dc = [0, 1, 0, -1]
direction = 0
segment_length = 1
steps = 0
while address < n * n - 1:
for _ in range(segment_length):
address += 1
r += dr[direction]
c += dc[direction]
if 0 <= r < n and 0 <= c < n:
spiral_map[r][c] = address
direction = (direction + 1) % 4
steps += 1
if steps % 2 == 0:
segment_length += 1
return spiral_map
def get_spiral_address(row, col, spiral_map):
"""
Converts a standard (row, col) address to a spiraling address
using a pre-computed map.
Args:
row (int): The row index (0-indexed).
col (int): The column index (0-indexed).
spiral_map (list of lists): The pre-computed spiral map.
Returns:
int: The spiraling address, or -1 if the coordinates are out of bounds.
"""
n = len(spiral_map)
if 0 <= row < n and 0 <= col < n:
return spiral_map[row][col]
else:
return -1
# Pre-compute the spiral map for a 5x5 matrix when the app starts
SPIRAL_MAP_5x5 = create_spiral_map(5)
# Initialize a 5x5 matrix with all lamps off (black color code)
lamp_matrix = [['#000000' for _ in range(5)] for _ in range(5)]
# Define a helper function to convert hex to RGB for template use
def hex_to_rgb(hex_color):
hex_color = hex_color.lstrip('#')
return {
'r': int(hex_color[0:2], 16),
'g': int(hex_color[2:4], 16),
'b': int(hex_color[4:6], 16)
}
app.jinja_env.globals.update(hex_to_rgb=hex_to_rgb)
@app.route('/')
def index():
"""
Renders the main control interface for the RGB lamp matrix.
"""
return render_template('index.html', matrix=lamp_matrix)
@app.route('/set_color', methods=['POST'])
def set_color():
"""
Sets the color for multiple lamps and turns all others black.
"""
data = request.get_json()
lamps_to_update = data.get('lamps', [])
r = data.get('r')
g = data.get('g')
b = data.get('b')
try:
r, g, b = int(r), int(g), int(b)
new_color = '#{:02x}{:02x}{:02x}'.format(r, g, b)
# First, turn all lamps black
for row in range(5):
for col in range(5):
lamp_matrix[row][col] = '#000000'
# Then, apply the new color to the selected lamps
for lamp in lamps_to_update:
row = lamp['row']
col = lamp['col']
if 0 <= row < 5 and 0 <= col < 5:
lamp_matrix[row][col] = new_color
print(get_spiral_address(row, col, SPIRAL_MAP_5x5))
return jsonify(success=True, new_color=new_color)
except (ValueError, TypeError, IndexError):
return jsonify(success=False, message="Invalid data received")
if __name__ == '__main__':
app.run(debug=True,host='0.0.0.0')

View File

@ -15,20 +15,19 @@
bool debugMode = true;
int bleCharCount;
const int channelPerLamp = 4;
int expectedLampCount = 25;
//DMX_PACKET_SIZE = 100;
const int expectedLampCount = 25;
const int dmxPacketSize = channelPerLamp * expectedLampCount + 1; //
struct Button {
const uint8_t PIN;
uint32_t numberKeyPresses;
bool pressed;
};
uint8_t dmxData[101] = {0};
uint8_t dmxData[DMX_PACKET_SIZE] = {0};
BLEServer* pServer = NULL;
bool deviceConnected = false;
bool oldDeviceConnected = false;
uint32_t value = 0;
uint16_t SERVICE_UUID = 20241115;
const int panelAmount = 25;
@ -53,7 +52,7 @@ const int modeAmount = 16;
uint8_t brightnessMax = 20;
uint8_t universalBrightness = 10;
uint8_t dataSeq[modeAmount][101] =
uint8_t dataSeq[modeAmount][DMX_PACKET_SIZE] =
{
{
0,
@ -295,8 +294,8 @@ void setup() {
bleCharCount = (panelAmount * debugMode) + !debugMode;
Serial.printf("\nCalculating BLE MTU ...");
uint16_t bleMTU = ((panelAmount * 3) / bleCharCount) + 3;
// Serial.printf("\nSetting BLE MTU to %i bytes... ", bleMTU);
// BLEDevice::setMTU(bleMTU + 3);
Serial.printf("\nSetting BLE MTU to %i bytes... ", bleMTU);
BLEDevice::setMTU(bleMTU + 3);
Serial.printf("Done!\n");
for (uint32_t i = 0; i < bleCharCount; i++){
@ -364,7 +363,7 @@ void loop() {
serialRead();
if (modeOld != mode){
Serial.printf("\nChanging Lighting Preset to Preset %d", mode);
uint8_t lampData[75];
uint8_t lampData[DMX_PACKET_SIZE / 4 * 3];
Serial.printf("\nDetected preset %i size: %i", mode, sizeof(dataSeq[mode]));
for (int i = 0; i < sizeof(dataSeq[mode]); i++){
dmxData[i] = dataSeq[mode][i];
@ -376,7 +375,7 @@ void loop() {
lampData[j] = dataSeq[mode][i];
}
};
pCharacteristics[0]->setValue(lampData, 75);
pCharacteristics[0]->setValue(lampData, expectedLampCount * 3);
}
Serial.printf("\nConstructing DMX Payload with size ");
for (int i = 0; i < bleCharCount; i++){
@ -388,7 +387,7 @@ void loop() {
int lampSum = i*3 + j;
int dmxAddress = (lampSum / 3) * 4 + lampSum % 3 + 1;
dmxData[dmxAddress] = packet;
Serial.printf("[[%i,%i] %i - %i] ",i , j, dmxAddress, packet);
// Serial.printf("[[%i,%i] %i - %i] ",i , j, dmxAddress, packet);
};
};
Serial.printf("\n");
@ -397,6 +396,6 @@ void loop() {
// Wait until the packet is finished being sent before proceeding.
dmx_wait_sent(DMX_NUM_1, DMX_TIMEOUT_TICK);
// Now write the packet synchronously!
dmx_write(DMX_NUM_1, dmxData, 100);
dmx_write(DMX_NUM_1, dmxData, DMX_PACKET_SIZE);
dmx_send(DMX_NUM_1);
}