Skip to content

CodeStructure.md

Trent M. Wyatt edited this page Apr 21, 2025 · 1 revision

Code Structure

Want to know what makes Bang tick? This page breaks down the source files in the Bang repository, showing how they team up to turn your Arduino into a host-dominating, self-reprogramming beast! From the Bang library firing off BANG("echo Hello") to arduino_exec.py handling ! (shell), & (uploads), and @ (macros) with a slick in-memory macro system, every file’s got a role in this command-line revolution. Built to stay lean for Arduino’s tight memory, Bang’s code is your ticket to epic projects. Let’s dive into the guts of this bad boy!

File Overview

The Bang repository is packed with files that split the work between the Arduino and the host (PC, Mac, or Linux). Here’s the lineup and what each one does:

File/Folder Purpose
Bang.h Header file defining the Bang class and macros (BANG, BANG_P, BANG_S) for sending !, &, and @ commands.
Bang.cpp Implements the Bang class, handling Serial-USB communication for commands and responses.
arduino_exec.py Python agent running on the host, processing ! (shell), & (uploads), and @ (macros, with dynamic management) from the Arduino.
examples/ Folder with example sketches (blink.ino, cmd.ino, music.ino, reboot.ino, upload.ino) showing Bang in action.
LICENSE MIT License file, copyrighted by Trent M. Wyatt (see License).

Detailed Breakdown

Bang.h

  • Role: The blueprint for the Bang class and its killer macros.
  • Key Components:
    • Class Definition:
      • Constructors for single or dual streams:

        Bang(Stream &stream); // Single Serial stream
        Bang(Stream &cmd, Stream &out); // Separate command/output streams
      • Methods like serial() to send commands (e.g., BANG("@play")).

    • Macros:
      • BANG(cmd): Sends a string literal (e.g., BANG("echo Hello")).
      • BANG_P(cmd): Sends from PROGMEM (e.g., BANG_P(PSTR("@weather"))).
      • BANG_S(cmd): Sends a String (e.g., BANG_S(String("&blink\n"))).
    • Used for ! (shell), & (uploads), and @ (macros, including @add_macro, @delete_macro).

Bang.cpp

  • Role: The muscle behind Bang.h, handling Serial communication.

  • Key Functions:

    • Sends commands with !, &, or @ prefixes to the host via serial().

    • Reads responses and forwards them to the output stream (e.g., Serial).

    • Example:

      ```cpp
      void Bang::serial(const char *cmd) {
          _cmd.print(cmd); // Send command (e.g., @play, !echo Hello)
          // Read and forward response
      }
      ```
      
  • Optimization: Keeps memory use low for Arduino’s constraints.

arduino_exec.py

  • Role: The host-side brain, listening for Arduino commands and making them happen.
  • Key Features:
    • Runs with sudo (e.g., sudo python3 arduino_exec.py -p /dev/cu.usbserial-00100 -b 38400).
    • Processes three command types:
      • !command: Executes shell commands (e.g., !echo Hello runs echo Hello).

      • &sketch_name\n: Uploads sketches (e.g., &blink\n uses arduino-cli).

      • @macro_name: Manages macros via an in-memory macros dictionary:

        • Invoke: @play runs macros["play"] (e.g., osascript ...).

        • Define: @add_macro:play:osascript -e 'tell application \"Music\" to play' adds to macros.

        • Delete: @delete_macro:play removes from macros.

        • List: @list_macros shows all macros.

          macros = {}  # In-memory dictionary
          if cmd_id == '@':
              if command in macros:
                  result = execute_command(macros[command])
              elif command == "list_macros":
                  macro_list = [f'    "{m}": "{macros[m]}"' for m in macros]
                  result = "Registered Macros:\n" + "\n".join(macro_list)
              elif command.startswith("add_macro:"):
                  _, macro_name, macro_cmd = command.split(":")
                  create_macro(macro_name, macro_cmd, macros)
                  result = f"Macro '{macro_name}' created with command '{macro_cmd}'"
              elif command.startswith("delete_macro:"):
                  _, macro_name = command.split(":")
                  result = delete_macro(macro_name, macros)
      • Macros are not saved to a file (e.g., macros.json); they reset on script restart.

    • See Python Agent for customization.

examples/

  • Role: Sketches showing Bang’s power.
  • Sketches:
    • blink.ino: Sends BANG("echo Blink Example"), blinks an LED.
    • cmd.ino: Sends multiple ! commands (e.g., BANG("date")).
    • music.ino: Controls music with BANG("osascript ..."), could use @play.
    • reboot.ino: Sends BANG("reboot") for host reboot.
    • upload.ino: Sends BANG("&blink\n") for self-reprogramming.
  • Purpose: Demonstrates ! and &; @macro can be added (e.g., BANG("@add_macro:play:osascript ...")).

LICENSE

  • Role: MIT License, letting you use, modify, and share Bang.
  • Details: Copyrighted by Trent M. Wyatt (see License).

How It All Fits Together

  • Arduino Side: Bang.h and Bang.cpp let sketches send BANG("!..."), BANG("&sketch_name\n"), or BANG("@macro_name") over Serial-USB.
  • Host Side: arduino_exec.py processes commands, storing macros in-memory for dynamic @add_macro/@delete_macro.
  • Workflow:
    • Sketch sends BANG("@add_macro:play:osascript ...")arduino_exec.py adds to macros.
    • Sketch sends BANG("@play")arduino_exec.py runs macros["play"].
    • Sketch sends BANG("&blink\n")arduino_exec.py uploads blink.ino.
  • Unlimited Apps: Sketches with Bang can send more commands, enabling endless subsystems (each ≤ 32K).

Future Potential

Macros are in-memory; future versions may add file-based storage (e.g., macros.json). Check GitHub for updates!

Next Steps


Back to Home | Next: Bang Class

Clone this wiki locally